aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/wm8971.c
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2009-07-05 12:24:50 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2009-07-05 12:24:50 -0400
commit17a52fd60a0a0e617ed94aadb1b19751a8fa219e (patch)
tree2c2fd4526ae219ec9435a0a4b0fc281a5ca62b7c /sound/soc/codecs/wm8971.c
parent5420f30723122012c7bb868a55ff21c7d383b68e (diff)
ASoC: Begin to factor out register cache I/O functions
A lot of CODECs share the same register data formats and therefore replicate the code to manage access to and caching of the register map. In order to reduce code duplication centralised versions of this code will be introduced with drivers able to configure the use of the common code by calling the new snd_soc_codec_set_cache_io() API call during startup. As an initial user the 7 bit address/9 bit data format used by many Wolfson devices is supported for write only CODECs and the drivers with straightforward register cache implementations are converted to use it. Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc/codecs/wm8971.c')
-rw-r--r--sound/soc/codecs/wm8971.c121
1 files changed, 44 insertions, 77 deletions
diff --git a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c
index 032dca22dbd3..53f3bc90ea0c 100644
--- a/sound/soc/codecs/wm8971.c
+++ b/sound/soc/codecs/wm8971.c
@@ -59,44 +59,7 @@ static const u16 wm8971_reg[] = {
59 0x0079, 0x0079, 0x0079, /* 40 */ 59 0x0079, 0x0079, 0x0079, /* 40 */
60}; 60};
61 61
62static inline unsigned int wm8971_read_reg_cache(struct snd_soc_codec *codec, 62#define wm8971_reset(c) snd_soc_write(c, WM8971_RESET, 0)
63 unsigned int reg)
64{
65 u16 *cache = codec->reg_cache;
66 if (reg < WM8971_REG_COUNT)
67 return cache[reg];
68
69 return -1;
70}
71
72static inline void wm8971_write_reg_cache(struct snd_soc_codec *codec,
73 unsigned int reg, unsigned int value)
74{
75 u16 *cache = codec->reg_cache;
76 if (reg < WM8971_REG_COUNT)
77 cache[reg] = value;
78}
79
80static int wm8971_write(struct snd_soc_codec *codec, unsigned int reg,
81 unsigned int value)
82{
83 u8 data[2];
84
85 /* data is
86 * D15..D9 WM8753 register offset
87 * D8...D0 register data
88 */
89 data[0] = (reg << 1) | ((value >> 8) & 0x0001);
90 data[1] = value & 0x00ff;
91
92 wm8971_write_reg_cache (codec, reg, value);
93 if (codec->hw_write(codec->control_data, data, 2) == 2)
94 return 0;
95 else
96 return -EIO;
97}
98
99#define wm8971_reset(c) wm8971_write(c, WM8971_RESET, 0)
100 63
101/* WM8971 Controls */ 64/* WM8971 Controls */
102static const char *wm8971_bass[] = { "Linear Control", "Adaptive Boost" }; 65static const char *wm8971_bass[] = { "Linear Control", "Adaptive Boost" };
@@ -521,7 +484,7 @@ static int wm8971_set_dai_fmt(struct snd_soc_dai *codec_dai,
521 return -EINVAL; 484 return -EINVAL;
522 } 485 }
523 486
524 wm8971_write(codec, WM8971_IFACE, iface); 487 snd_soc_write(codec, WM8971_IFACE, iface);
525 return 0; 488 return 0;
526} 489}
527 490
@@ -533,8 +496,8 @@ static int wm8971_pcm_hw_params(struct snd_pcm_substream *substream,
533 struct snd_soc_device *socdev = rtd->socdev; 496 struct snd_soc_device *socdev = rtd->socdev;
534 struct snd_soc_codec *codec = socdev->card->codec; 497 struct snd_soc_codec *codec = socdev->card->codec;
535 struct wm8971_priv *wm8971 = codec->private_data; 498 struct wm8971_priv *wm8971 = codec->private_data;
536 u16 iface = wm8971_read_reg_cache(codec, WM8971_IFACE) & 0x1f3; 499 u16 iface = snd_soc_read(codec, WM8971_IFACE) & 0x1f3;
537 u16 srate = wm8971_read_reg_cache(codec, WM8971_SRATE) & 0x1c0; 500 u16 srate = snd_soc_read(codec, WM8971_SRATE) & 0x1c0;
538 int coeff = get_coeff(wm8971->sysclk, params_rate(params)); 501 int coeff = get_coeff(wm8971->sysclk, params_rate(params));
539 502
540 /* bit size */ 503 /* bit size */
@@ -553,9 +516,9 @@ static int wm8971_pcm_hw_params(struct snd_pcm_substream *substream,
553 } 516 }
554 517
555 /* set iface & srate */ 518 /* set iface & srate */
556 wm8971_write(codec, WM8971_IFACE, iface); 519 snd_soc_write(codec, WM8971_IFACE, iface);
557 if (coeff >= 0) 520 if (coeff >= 0)
558 wm8971_write(codec, WM8971_SRATE, srate | 521 snd_soc_write(codec, WM8971_SRATE, srate |
559 (coeff_div[coeff].sr << 1) | coeff_div[coeff].usb); 522 (coeff_div[coeff].sr << 1) | coeff_div[coeff].usb);
560 523
561 return 0; 524 return 0;
@@ -564,33 +527,33 @@ static int wm8971_pcm_hw_params(struct snd_pcm_substream *substream,
564static int wm8971_mute(struct snd_soc_dai *dai, int mute) 527static int wm8971_mute(struct snd_soc_dai *dai, int mute)
565{ 528{
566 struct snd_soc_codec *codec = dai->codec; 529 struct snd_soc_codec *codec = dai->codec;
567 u16 mute_reg = wm8971_read_reg_cache(codec, WM8971_ADCDAC) & 0xfff7; 530 u16 mute_reg = snd_soc_read(codec, WM8971_ADCDAC) & 0xfff7;
568 531
569 if (mute) 532 if (mute)
570 wm8971_write(codec, WM8971_ADCDAC, mute_reg | 0x8); 533 snd_soc_write(codec, WM8971_ADCDAC, mute_reg | 0x8);
571 else 534 else
572 wm8971_write(codec, WM8971_ADCDAC, mute_reg); 535 snd_soc_write(codec, WM8971_ADCDAC, mute_reg);
573 return 0; 536 return 0;
574} 537}
575 538
576static int wm8971_set_bias_level(struct snd_soc_codec *codec, 539static int wm8971_set_bias_level(struct snd_soc_codec *codec,
577 enum snd_soc_bias_level level) 540 enum snd_soc_bias_level level)
578{ 541{
579 u16 pwr_reg = wm8971_read_reg_cache(codec, WM8971_PWR1) & 0xfe3e; 542 u16 pwr_reg = snd_soc_read(codec, WM8971_PWR1) & 0xfe3e;
580 543
581 switch (level) { 544 switch (level) {
582 case SND_SOC_BIAS_ON: 545 case SND_SOC_BIAS_ON:
583 /* set vmid to 50k and unmute dac */ 546 /* set vmid to 50k and unmute dac */
584 wm8971_write(codec, WM8971_PWR1, pwr_reg | 0x00c1); 547 snd_soc_write(codec, WM8971_PWR1, pwr_reg | 0x00c1);
585 break; 548 break;
586 case SND_SOC_BIAS_PREPARE: 549 case SND_SOC_BIAS_PREPARE:
587 break; 550 break;
588 case SND_SOC_BIAS_STANDBY: 551 case SND_SOC_BIAS_STANDBY:
589 /* mute dac and set vmid to 500k, enable VREF */ 552 /* mute dac and set vmid to 500k, enable VREF */
590 wm8971_write(codec, WM8971_PWR1, pwr_reg | 0x0140); 553 snd_soc_write(codec, WM8971_PWR1, pwr_reg | 0x0140);
591 break; 554 break;
592 case SND_SOC_BIAS_OFF: 555 case SND_SOC_BIAS_OFF:
593 wm8971_write(codec, WM8971_PWR1, 0x0001); 556 snd_soc_write(codec, WM8971_PWR1, 0x0001);
594 break; 557 break;
595 } 558 }
596 codec->bias_level = level; 559 codec->bias_level = level;
@@ -667,8 +630,8 @@ static int wm8971_resume(struct platform_device *pdev)
667 630
668 /* charge wm8971 caps */ 631 /* charge wm8971 caps */
669 if (codec->suspend_bias_level == SND_SOC_BIAS_ON) { 632 if (codec->suspend_bias_level == SND_SOC_BIAS_ON) {
670 reg = wm8971_read_reg_cache(codec, WM8971_PWR1) & 0xfe3e; 633 reg = snd_soc_read(codec, WM8971_PWR1) & 0xfe3e;
671 wm8971_write(codec, WM8971_PWR1, reg | 0x01c0); 634 snd_soc_write(codec, WM8971_PWR1, reg | 0x01c0);
672 codec->bias_level = SND_SOC_BIAS_ON; 635 codec->bias_level = SND_SOC_BIAS_ON;
673 queue_delayed_work(wm8971_workq, &codec->delayed_work, 636 queue_delayed_work(wm8971_workq, &codec->delayed_work,
674 msecs_to_jiffies(1000)); 637 msecs_to_jiffies(1000));
@@ -684,8 +647,6 @@ static int wm8971_init(struct snd_soc_device *socdev)
684 647
685 codec->name = "WM8971"; 648 codec->name = "WM8971";
686 codec->owner = THIS_MODULE; 649 codec->owner = THIS_MODULE;
687 codec->read = wm8971_read_reg_cache;
688 codec->write = wm8971_write;
689 codec->set_bias_level = wm8971_set_bias_level; 650 codec->set_bias_level = wm8971_set_bias_level;
690 codec->dai = &wm8971_dai; 651 codec->dai = &wm8971_dai;
691 codec->reg_cache_size = ARRAY_SIZE(wm8971_reg); 652 codec->reg_cache_size = ARRAY_SIZE(wm8971_reg);
@@ -695,42 +656,48 @@ static int wm8971_init(struct snd_soc_device *socdev)
695 if (codec->reg_cache == NULL) 656 if (codec->reg_cache == NULL)
696 return -ENOMEM; 657 return -ENOMEM;
697 658
659 ret = snd_soc_codec_set_cache_io(codec, 7, 9);
660 if (ret < 0) {
661 printk(KERN_ERR "wm8971: failed to set cache I/O: %d\n", ret);
662 goto err;
663 }
664
698 wm8971_reset(codec); 665 wm8971_reset(codec);
699 666
700 /* register pcms */ 667 /* register pcms */
701 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); 668 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
702 if (ret < 0) { 669 if (ret < 0) {
703 printk(KERN_ERR "wm8971: failed to create pcms\n"); 670 printk(KERN_ERR "wm8971: failed to create pcms\n");
704 goto pcm_err; 671 goto err;
705 } 672 }
706 673
707 /* charge output caps - set vmid to 5k for quick power up */ 674 /* charge output caps - set vmid to 5k for quick power up */
708 reg = wm8971_read_reg_cache(codec, WM8971_PWR1) & 0xfe3e; 675 reg = snd_soc_read(codec, WM8971_PWR1) & 0xfe3e;
709 wm8971_write(codec, WM8971_PWR1, reg | 0x01c0); 676 snd_soc_write(codec, WM8971_PWR1, reg | 0x01c0);
710 codec->bias_level = SND_SOC_BIAS_STANDBY; 677 codec->bias_level = SND_SOC_BIAS_STANDBY;
711 queue_delayed_work(wm8971_workq, &codec->delayed_work, 678 queue_delayed_work(wm8971_workq, &codec->delayed_work,
712 msecs_to_jiffies(1000)); 679 msecs_to_jiffies(1000));
713 680
714 /* set the update bits */ 681 /* set the update bits */
715 reg = wm8971_read_reg_cache(codec, WM8971_LDAC); 682 reg = snd_soc_read(codec, WM8971_LDAC);
716 wm8971_write(codec, WM8971_LDAC, reg | 0x0100); 683 snd_soc_write(codec, WM8971_LDAC, reg | 0x0100);
717 reg = wm8971_read_reg_cache(codec, WM8971_RDAC); 684 reg = snd_soc_read(codec, WM8971_RDAC);
718 wm8971_write(codec, WM8971_RDAC, reg | 0x0100); 685 snd_soc_write(codec, WM8971_RDAC, reg | 0x0100);
719 686
720 reg = wm8971_read_reg_cache(codec, WM8971_LOUT1V); 687 reg = snd_soc_read(codec, WM8971_LOUT1V);
721 wm8971_write(codec, WM8971_LOUT1V, reg | 0x0100); 688 snd_soc_write(codec, WM8971_LOUT1V, reg | 0x0100);
722 reg = wm8971_read_reg_cache(codec, WM8971_ROUT1V); 689 reg = snd_soc_read(codec, WM8971_ROUT1V);
723 wm8971_write(codec, WM8971_ROUT1V, reg | 0x0100); 690 snd_soc_write(codec, WM8971_ROUT1V, reg | 0x0100);
724 691
725 reg = wm8971_read_reg_cache(codec, WM8971_LOUT2V); 692 reg = snd_soc_read(codec, WM8971_LOUT2V);
726 wm8971_write(codec, WM8971_LOUT2V, reg | 0x0100); 693 snd_soc_write(codec, WM8971_LOUT2V, reg | 0x0100);
727 reg = wm8971_read_reg_cache(codec, WM8971_ROUT2V); 694 reg = snd_soc_read(codec, WM8971_ROUT2V);
728 wm8971_write(codec, WM8971_ROUT2V, reg | 0x0100); 695 snd_soc_write(codec, WM8971_ROUT2V, reg | 0x0100);
729 696
730 reg = wm8971_read_reg_cache(codec, WM8971_LINVOL); 697 reg = snd_soc_read(codec, WM8971_LINVOL);
731 wm8971_write(codec, WM8971_LINVOL, reg | 0x0100); 698 snd_soc_write(codec, WM8971_LINVOL, reg | 0x0100);
732 reg = wm8971_read_reg_cache(codec, WM8971_RINVOL); 699 reg = snd_soc_read(codec, WM8971_RINVOL);
733 wm8971_write(codec, WM8971_RINVOL, reg | 0x0100); 700 snd_soc_write(codec, WM8971_RINVOL, reg | 0x0100);
734 701
735 snd_soc_add_controls(codec, wm8971_snd_controls, 702 snd_soc_add_controls(codec, wm8971_snd_controls,
736 ARRAY_SIZE(wm8971_snd_controls)); 703 ARRAY_SIZE(wm8971_snd_controls));
@@ -745,7 +712,7 @@ static int wm8971_init(struct snd_soc_device *socdev)
745card_err: 712card_err:
746 snd_soc_free_pcms(socdev); 713 snd_soc_free_pcms(socdev);
747 snd_soc_dapm_free(socdev); 714 snd_soc_dapm_free(socdev);
748pcm_err: 715err:
749 kfree(codec->reg_cache); 716 kfree(codec->reg_cache);
750 return ret; 717 return ret;
751} 718}