diff options
author | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2009-08-07 06:43:58 -0400 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2009-08-07 06:43:58 -0400 |
commit | 06cddefc1f25b847dafe392f3d5781482b3395b5 (patch) | |
tree | 97f4df2e4ae6a1e8194ca67ede1b552802ba2334 /sound/soc/codecs/wm8971.c | |
parent | b9b5cc26d0b3a9b361cc56c3a3b0d6f819b9195f (diff) | |
parent | 27ded041f03026e8c6be9efc626e11ddfb4620c1 (diff) |
Merge branch 'reg-cache' into for-2.6.32
Diffstat (limited to 'sound/soc/codecs/wm8971.c')
-rw-r--r-- | sound/soc/codecs/wm8971.c | 127 |
1 files changed, 47 insertions, 80 deletions
diff --git a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c index 032dca22dbd3..d66efb0546ea 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 | ||
62 | static 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 | |||
72 | static 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 | |||
80 | static 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 */ |
102 | static const char *wm8971_bass[] = { "Linear Control", "Adaptive Boost" }; | 65 | static 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, | |||
564 | static int wm8971_mute(struct snd_soc_dai *dai, int mute) | 527 | static 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 | ||
576 | static int wm8971_set_bias_level(struct snd_soc_codec *codec, | 539 | static 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)); |
@@ -677,15 +640,14 @@ static int wm8971_resume(struct platform_device *pdev) | |||
677 | return 0; | 640 | return 0; |
678 | } | 641 | } |
679 | 642 | ||
680 | static int wm8971_init(struct snd_soc_device *socdev) | 643 | static int wm8971_init(struct snd_soc_device *socdev, |
644 | enum snd_soc_control_type control) | ||
681 | { | 645 | { |
682 | struct snd_soc_codec *codec = socdev->card->codec; | 646 | struct snd_soc_codec *codec = socdev->card->codec; |
683 | int reg, ret = 0; | 647 | int reg, ret = 0; |
684 | 648 | ||
685 | codec->name = "WM8971"; | 649 | codec->name = "WM8971"; |
686 | codec->owner = THIS_MODULE; | 650 | 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; | 651 | codec->set_bias_level = wm8971_set_bias_level; |
690 | codec->dai = &wm8971_dai; | 652 | codec->dai = &wm8971_dai; |
691 | codec->reg_cache_size = ARRAY_SIZE(wm8971_reg); | 653 | codec->reg_cache_size = ARRAY_SIZE(wm8971_reg); |
@@ -695,42 +657,48 @@ static int wm8971_init(struct snd_soc_device *socdev) | |||
695 | if (codec->reg_cache == NULL) | 657 | if (codec->reg_cache == NULL) |
696 | return -ENOMEM; | 658 | return -ENOMEM; |
697 | 659 | ||
660 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); | ||
661 | if (ret < 0) { | ||
662 | printk(KERN_ERR "wm8971: failed to set cache I/O: %d\n", ret); | ||
663 | goto err; | ||
664 | } | ||
665 | |||
698 | wm8971_reset(codec); | 666 | wm8971_reset(codec); |
699 | 667 | ||
700 | /* register pcms */ | 668 | /* register pcms */ |
701 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | 669 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); |
702 | if (ret < 0) { | 670 | if (ret < 0) { |
703 | printk(KERN_ERR "wm8971: failed to create pcms\n"); | 671 | printk(KERN_ERR "wm8971: failed to create pcms\n"); |
704 | goto pcm_err; | 672 | goto err; |
705 | } | 673 | } |
706 | 674 | ||
707 | /* charge output caps - set vmid to 5k for quick power up */ | 675 | /* charge output caps - set vmid to 5k for quick power up */ |
708 | reg = wm8971_read_reg_cache(codec, WM8971_PWR1) & 0xfe3e; | 676 | reg = snd_soc_read(codec, WM8971_PWR1) & 0xfe3e; |
709 | wm8971_write(codec, WM8971_PWR1, reg | 0x01c0); | 677 | snd_soc_write(codec, WM8971_PWR1, reg | 0x01c0); |
710 | codec->bias_level = SND_SOC_BIAS_STANDBY; | 678 | codec->bias_level = SND_SOC_BIAS_STANDBY; |
711 | queue_delayed_work(wm8971_workq, &codec->delayed_work, | 679 | queue_delayed_work(wm8971_workq, &codec->delayed_work, |
712 | msecs_to_jiffies(1000)); | 680 | msecs_to_jiffies(1000)); |
713 | 681 | ||
714 | /* set the update bits */ | 682 | /* set the update bits */ |
715 | reg = wm8971_read_reg_cache(codec, WM8971_LDAC); | 683 | reg = snd_soc_read(codec, WM8971_LDAC); |
716 | wm8971_write(codec, WM8971_LDAC, reg | 0x0100); | 684 | snd_soc_write(codec, WM8971_LDAC, reg | 0x0100); |
717 | reg = wm8971_read_reg_cache(codec, WM8971_RDAC); | 685 | reg = snd_soc_read(codec, WM8971_RDAC); |
718 | wm8971_write(codec, WM8971_RDAC, reg | 0x0100); | 686 | snd_soc_write(codec, WM8971_RDAC, reg | 0x0100); |
719 | 687 | ||
720 | reg = wm8971_read_reg_cache(codec, WM8971_LOUT1V); | 688 | reg = snd_soc_read(codec, WM8971_LOUT1V); |
721 | wm8971_write(codec, WM8971_LOUT1V, reg | 0x0100); | 689 | snd_soc_write(codec, WM8971_LOUT1V, reg | 0x0100); |
722 | reg = wm8971_read_reg_cache(codec, WM8971_ROUT1V); | 690 | reg = snd_soc_read(codec, WM8971_ROUT1V); |
723 | wm8971_write(codec, WM8971_ROUT1V, reg | 0x0100); | 691 | snd_soc_write(codec, WM8971_ROUT1V, reg | 0x0100); |
724 | 692 | ||
725 | reg = wm8971_read_reg_cache(codec, WM8971_LOUT2V); | 693 | reg = snd_soc_read(codec, WM8971_LOUT2V); |
726 | wm8971_write(codec, WM8971_LOUT2V, reg | 0x0100); | 694 | snd_soc_write(codec, WM8971_LOUT2V, reg | 0x0100); |
727 | reg = wm8971_read_reg_cache(codec, WM8971_ROUT2V); | 695 | reg = snd_soc_read(codec, WM8971_ROUT2V); |
728 | wm8971_write(codec, WM8971_ROUT2V, reg | 0x0100); | 696 | snd_soc_write(codec, WM8971_ROUT2V, reg | 0x0100); |
729 | 697 | ||
730 | reg = wm8971_read_reg_cache(codec, WM8971_LINVOL); | 698 | reg = snd_soc_read(codec, WM8971_LINVOL); |
731 | wm8971_write(codec, WM8971_LINVOL, reg | 0x0100); | 699 | snd_soc_write(codec, WM8971_LINVOL, reg | 0x0100); |
732 | reg = wm8971_read_reg_cache(codec, WM8971_RINVOL); | 700 | reg = snd_soc_read(codec, WM8971_RINVOL); |
733 | wm8971_write(codec, WM8971_RINVOL, reg | 0x0100); | 701 | snd_soc_write(codec, WM8971_RINVOL, reg | 0x0100); |
734 | 702 | ||
735 | snd_soc_add_controls(codec, wm8971_snd_controls, | 703 | snd_soc_add_controls(codec, wm8971_snd_controls, |
736 | ARRAY_SIZE(wm8971_snd_controls)); | 704 | ARRAY_SIZE(wm8971_snd_controls)); |
@@ -745,7 +713,7 @@ static int wm8971_init(struct snd_soc_device *socdev) | |||
745 | card_err: | 713 | card_err: |
746 | snd_soc_free_pcms(socdev); | 714 | snd_soc_free_pcms(socdev); |
747 | snd_soc_dapm_free(socdev); | 715 | snd_soc_dapm_free(socdev); |
748 | pcm_err: | 716 | err: |
749 | kfree(codec->reg_cache); | 717 | kfree(codec->reg_cache); |
750 | return ret; | 718 | return ret; |
751 | } | 719 | } |
@@ -767,7 +735,7 @@ static int wm8971_i2c_probe(struct i2c_client *i2c, | |||
767 | 735 | ||
768 | codec->control_data = i2c; | 736 | codec->control_data = i2c; |
769 | 737 | ||
770 | ret = wm8971_init(socdev); | 738 | ret = wm8971_init(socdev, SND_SOC_I2C); |
771 | if (ret < 0) | 739 | if (ret < 0) |
772 | pr_err("failed to initialise WM8971\n"); | 740 | pr_err("failed to initialise WM8971\n"); |
773 | 741 | ||
@@ -877,7 +845,6 @@ static int wm8971_probe(struct platform_device *pdev) | |||
877 | 845 | ||
878 | #if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE) | 846 | #if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE) |
879 | if (setup->i2c_address) { | 847 | if (setup->i2c_address) { |
880 | codec->hw_write = (hw_write_t)i2c_master_send; | ||
881 | ret = wm8971_add_i2c_device(pdev, setup); | 848 | ret = wm8971_add_i2c_device(pdev, setup); |
882 | } | 849 | } |
883 | #endif | 850 | #endif |