wm8988.c (0cce284537fb42d9c28b9b31038ffc9b464555f5) wm8988.c (ab38ff38bc77330c009f918680501b9dc37a9b3e)
1/*
2 * wm8988.c -- WM8988 ALSA SoC audio driver
3 *
4 * Copyright 2009 Wolfson Microelectronics plc
5 * Copyright 2005 Openedhand Ltd.
6 *
7 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
8 *

--- 105 unchanged lines hidden (view full) ---

114
115/* codec private data */
116struct wm8988_priv {
117 struct regmap *regmap;
118 unsigned int sysclk;
119 const struct snd_pcm_hw_constraint_list *sysclk_constraints;
120};
121
1/*
2 * wm8988.c -- WM8988 ALSA SoC audio driver
3 *
4 * Copyright 2009 Wolfson Microelectronics plc
5 * Copyright 2005 Openedhand Ltd.
6 *
7 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
8 *

--- 105 unchanged lines hidden (view full) ---

114
115/* codec private data */
116struct wm8988_priv {
117 struct regmap *regmap;
118 unsigned int sysclk;
119 const struct snd_pcm_hw_constraint_list *sysclk_constraints;
120};
121
122#define wm8988_reset(c) snd_soc_write(c, WM8988_RESET, 0)
122#define wm8988_reset(c) snd_soc_component_write(c, WM8988_RESET, 0)
123
124/*
125 * WM8988 Controls
126 */
127
128static const char *bass_boost_txt[] = {"Linear Control", "Adaptive Boost"};
129static SOC_ENUM_SINGLE_DECL(bass_boost,
130 WM8988_BASS, 7, bass_boost_txt);

--- 108 unchanged lines hidden (view full) ---

239
240/*
241 * DAPM Controls
242 */
243
244static int wm8988_lrc_control(struct snd_soc_dapm_widget *w,
245 struct snd_kcontrol *kcontrol, int event)
246{
123
124/*
125 * WM8988 Controls
126 */
127
128static const char *bass_boost_txt[] = {"Linear Control", "Adaptive Boost"};
129static SOC_ENUM_SINGLE_DECL(bass_boost,
130 WM8988_BASS, 7, bass_boost_txt);

--- 108 unchanged lines hidden (view full) ---

239
240/*
241 * DAPM Controls
242 */
243
244static int wm8988_lrc_control(struct snd_soc_dapm_widget *w,
245 struct snd_kcontrol *kcontrol, int event)
246{
247 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
248 u16 adctl2 = snd_soc_read(codec, WM8988_ADCTL2);
247 struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm);
248 u16 adctl2 = snd_soc_component_read32(component, WM8988_ADCTL2);
249
250 /* Use the DAC to gate LRC if active, otherwise use ADC */
249
250 /* Use the DAC to gate LRC if active, otherwise use ADC */
251 if (snd_soc_read(codec, WM8988_PWR2) & 0x180)
251 if (snd_soc_component_read32(component, WM8988_PWR2) & 0x180)
252 adctl2 &= ~0x4;
253 else
254 adctl2 |= 0x4;
255
252 adctl2 &= ~0x4;
253 else
254 adctl2 |= 0x4;
255
256 return snd_soc_write(codec, WM8988_ADCTL2, adctl2);
256 return snd_soc_component_write(component, WM8988_ADCTL2, adctl2);
257}
258
259static const char *wm8988_line_texts[] = {
260 "Line 1", "Line 2", "PGA", "Differential"};
261
262static const unsigned int wm8988_line_values[] = {
263 0, 1, 3, 4};
264

--- 285 unchanged lines hidden (view full) ---

550};
551
552/*
553 * Note that this should be called from init rather than from hw_params.
554 */
555static int wm8988_set_dai_sysclk(struct snd_soc_dai *codec_dai,
556 int clk_id, unsigned int freq, int dir)
557{
257}
258
259static const char *wm8988_line_texts[] = {
260 "Line 1", "Line 2", "PGA", "Differential"};
261
262static const unsigned int wm8988_line_values[] = {
263 0, 1, 3, 4};
264

--- 285 unchanged lines hidden (view full) ---

550};
551
552/*
553 * Note that this should be called from init rather than from hw_params.
554 */
555static int wm8988_set_dai_sysclk(struct snd_soc_dai *codec_dai,
556 int clk_id, unsigned int freq, int dir)
557{
558 struct snd_soc_codec *codec = codec_dai->codec;
559 struct wm8988_priv *wm8988 = snd_soc_codec_get_drvdata(codec);
558 struct snd_soc_component *component = codec_dai->component;
559 struct wm8988_priv *wm8988 = snd_soc_component_get_drvdata(component);
560
561 switch (freq) {
562 case 11289600:
563 case 18432000:
564 case 22579200:
565 case 36864000:
566 wm8988->sysclk_constraints = &constraints_112896;
567 wm8988->sysclk = freq;

--- 14 unchanged lines hidden (view full) ---

582 return 0;
583 }
584 return -EINVAL;
585}
586
587static int wm8988_set_dai_fmt(struct snd_soc_dai *codec_dai,
588 unsigned int fmt)
589{
560
561 switch (freq) {
562 case 11289600:
563 case 18432000:
564 case 22579200:
565 case 36864000:
566 wm8988->sysclk_constraints = &constraints_112896;
567 wm8988->sysclk = freq;

--- 14 unchanged lines hidden (view full) ---

582 return 0;
583 }
584 return -EINVAL;
585}
586
587static int wm8988_set_dai_fmt(struct snd_soc_dai *codec_dai,
588 unsigned int fmt)
589{
590 struct snd_soc_codec *codec = codec_dai->codec;
590 struct snd_soc_component *component = codec_dai->component;
591 u16 iface = 0;
592
593 /* set master/slave audio interface */
594 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
595 case SND_SOC_DAIFMT_CBM_CFM:
596 iface = 0x0040;
597 break;
598 case SND_SOC_DAIFMT_CBS_CFS:

--- 34 unchanged lines hidden (view full) ---

633 break;
634 case SND_SOC_DAIFMT_NB_IF:
635 iface |= 0x0010;
636 break;
637 default:
638 return -EINVAL;
639 }
640
591 u16 iface = 0;
592
593 /* set master/slave audio interface */
594 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
595 case SND_SOC_DAIFMT_CBM_CFM:
596 iface = 0x0040;
597 break;
598 case SND_SOC_DAIFMT_CBS_CFS:

--- 34 unchanged lines hidden (view full) ---

633 break;
634 case SND_SOC_DAIFMT_NB_IF:
635 iface |= 0x0010;
636 break;
637 default:
638 return -EINVAL;
639 }
640
641 snd_soc_write(codec, WM8988_IFACE, iface);
641 snd_soc_component_write(component, WM8988_IFACE, iface);
642 return 0;
643}
644
645static int wm8988_pcm_startup(struct snd_pcm_substream *substream,
646 struct snd_soc_dai *dai)
647{
642 return 0;
643}
644
645static int wm8988_pcm_startup(struct snd_pcm_substream *substream,
646 struct snd_soc_dai *dai)
647{
648 struct snd_soc_codec *codec = dai->codec;
649 struct wm8988_priv *wm8988 = snd_soc_codec_get_drvdata(codec);
648 struct snd_soc_component *component = dai->component;
649 struct wm8988_priv *wm8988 = snd_soc_component_get_drvdata(component);
650
651 /* The set of sample rates that can be supported depends on the
652 * MCLK supplied to the CODEC - enforce this.
653 */
654 if (!wm8988->sysclk) {
650
651 /* The set of sample rates that can be supported depends on the
652 * MCLK supplied to the CODEC - enforce this.
653 */
654 if (!wm8988->sysclk) {
655 dev_err(codec->dev,
655 dev_err(component->dev,
656 "No MCLK configured, call set_sysclk() on init\n");
657 return -EINVAL;
658 }
659
660 snd_pcm_hw_constraint_list(substream->runtime, 0,
661 SNDRV_PCM_HW_PARAM_RATE,
662 wm8988->sysclk_constraints);
663
664 return 0;
665}
666
667static int wm8988_pcm_hw_params(struct snd_pcm_substream *substream,
668 struct snd_pcm_hw_params *params,
669 struct snd_soc_dai *dai)
670{
656 "No MCLK configured, call set_sysclk() on init\n");
657 return -EINVAL;
658 }
659
660 snd_pcm_hw_constraint_list(substream->runtime, 0,
661 SNDRV_PCM_HW_PARAM_RATE,
662 wm8988->sysclk_constraints);
663
664 return 0;
665}
666
667static int wm8988_pcm_hw_params(struct snd_pcm_substream *substream,
668 struct snd_pcm_hw_params *params,
669 struct snd_soc_dai *dai)
670{
671 struct snd_soc_codec *codec = dai->codec;
672 struct wm8988_priv *wm8988 = snd_soc_codec_get_drvdata(codec);
673 u16 iface = snd_soc_read(codec, WM8988_IFACE) & 0x1f3;
674 u16 srate = snd_soc_read(codec, WM8988_SRATE) & 0x180;
671 struct snd_soc_component *component = dai->component;
672 struct wm8988_priv *wm8988 = snd_soc_component_get_drvdata(component);
673 u16 iface = snd_soc_component_read32(component, WM8988_IFACE) & 0x1f3;
674 u16 srate = snd_soc_component_read32(component, WM8988_SRATE) & 0x180;
675 int coeff;
676
677 coeff = get_coeff(wm8988->sysclk, params_rate(params));
678 if (coeff < 0) {
679 coeff = get_coeff(wm8988->sysclk / 2, params_rate(params));
680 srate |= 0x40;
681 }
682 if (coeff < 0) {
675 int coeff;
676
677 coeff = get_coeff(wm8988->sysclk, params_rate(params));
678 if (coeff < 0) {
679 coeff = get_coeff(wm8988->sysclk / 2, params_rate(params));
680 srate |= 0x40;
681 }
682 if (coeff < 0) {
683 dev_err(codec->dev,
683 dev_err(component->dev,
684 "Unable to configure sample rate %dHz with %dHz MCLK\n",
685 params_rate(params), wm8988->sysclk);
686 return coeff;
687 }
688
689 /* bit size */
690 switch (params_width(params)) {
691 case 16:

--- 5 unchanged lines hidden (view full) ---

697 iface |= 0x0008;
698 break;
699 case 32:
700 iface |= 0x000c;
701 break;
702 }
703
704 /* set iface & srate */
684 "Unable to configure sample rate %dHz with %dHz MCLK\n",
685 params_rate(params), wm8988->sysclk);
686 return coeff;
687 }
688
689 /* bit size */
690 switch (params_width(params)) {
691 case 16:

--- 5 unchanged lines hidden (view full) ---

697 iface |= 0x0008;
698 break;
699 case 32:
700 iface |= 0x000c;
701 break;
702 }
703
704 /* set iface & srate */
705 snd_soc_write(codec, WM8988_IFACE, iface);
705 snd_soc_component_write(component, WM8988_IFACE, iface);
706 if (coeff >= 0)
706 if (coeff >= 0)
707 snd_soc_write(codec, WM8988_SRATE, srate |
707 snd_soc_component_write(component, WM8988_SRATE, srate |
708 (coeff_div[coeff].sr << 1) | coeff_div[coeff].usb);
709
710 return 0;
711}
712
713static int wm8988_mute(struct snd_soc_dai *dai, int mute)
714{
708 (coeff_div[coeff].sr << 1) | coeff_div[coeff].usb);
709
710 return 0;
711}
712
713static int wm8988_mute(struct snd_soc_dai *dai, int mute)
714{
715 struct snd_soc_codec *codec = dai->codec;
716 u16 mute_reg = snd_soc_read(codec, WM8988_ADCDAC) & 0xfff7;
715 struct snd_soc_component *component = dai->component;
716 u16 mute_reg = snd_soc_component_read32(component, WM8988_ADCDAC) & 0xfff7;
717
718 if (mute)
717
718 if (mute)
719 snd_soc_write(codec, WM8988_ADCDAC, mute_reg | 0x8);
719 snd_soc_component_write(component, WM8988_ADCDAC, mute_reg | 0x8);
720 else
720 else
721 snd_soc_write(codec, WM8988_ADCDAC, mute_reg);
721 snd_soc_component_write(component, WM8988_ADCDAC, mute_reg);
722 return 0;
723}
724
722 return 0;
723}
724
725static int wm8988_set_bias_level(struct snd_soc_codec *codec,
725static int wm8988_set_bias_level(struct snd_soc_component *component,
726 enum snd_soc_bias_level level)
727{
726 enum snd_soc_bias_level level)
727{
728 struct wm8988_priv *wm8988 = snd_soc_codec_get_drvdata(codec);
729 u16 pwr_reg = snd_soc_read(codec, WM8988_PWR1) & ~0x1c1;
728 struct wm8988_priv *wm8988 = snd_soc_component_get_drvdata(component);
729 u16 pwr_reg = snd_soc_component_read32(component, WM8988_PWR1) & ~0x1c1;
730
731 switch (level) {
732 case SND_SOC_BIAS_ON:
733 break;
734
735 case SND_SOC_BIAS_PREPARE:
736 /* VREF, VMID=2x50k, digital enabled */
730
731 switch (level) {
732 case SND_SOC_BIAS_ON:
733 break;
734
735 case SND_SOC_BIAS_PREPARE:
736 /* VREF, VMID=2x50k, digital enabled */
737 snd_soc_write(codec, WM8988_PWR1, pwr_reg | 0x00c0);
737 snd_soc_component_write(component, WM8988_PWR1, pwr_reg | 0x00c0);
738 break;
739
740 case SND_SOC_BIAS_STANDBY:
738 break;
739
740 case SND_SOC_BIAS_STANDBY:
741 if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) {
741 if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF) {
742 regcache_sync(wm8988->regmap);
743
744 /* VREF, VMID=2x5k */
742 regcache_sync(wm8988->regmap);
743
744 /* VREF, VMID=2x5k */
745 snd_soc_write(codec, WM8988_PWR1, pwr_reg | 0x1c1);
745 snd_soc_component_write(component, WM8988_PWR1, pwr_reg | 0x1c1);
746
747 /* Charge caps */
748 msleep(100);
749 }
750
751 /* VREF, VMID=2*500k, digital stopped */
746
747 /* Charge caps */
748 msleep(100);
749 }
750
751 /* VREF, VMID=2*500k, digital stopped */
752 snd_soc_write(codec, WM8988_PWR1, pwr_reg | 0x0141);
752 snd_soc_component_write(component, WM8988_PWR1, pwr_reg | 0x0141);
753 break;
754
755 case SND_SOC_BIAS_OFF:
753 break;
754
755 case SND_SOC_BIAS_OFF:
756 snd_soc_write(codec, WM8988_PWR1, 0x0000);
756 snd_soc_component_write(component, WM8988_PWR1, 0x0000);
757 break;
758 }
759 return 0;
760}
761
762#define WM8988_RATES SNDRV_PCM_RATE_8000_96000
763
764#define WM8988_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\

--- 22 unchanged lines hidden (view full) ---

787 .channels_max = 2,
788 .rates = WM8988_RATES,
789 .formats = WM8988_FORMATS,
790 },
791 .ops = &wm8988_ops,
792 .symmetric_rates = 1,
793};
794
757 break;
758 }
759 return 0;
760}
761
762#define WM8988_RATES SNDRV_PCM_RATE_8000_96000
763
764#define WM8988_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\

--- 22 unchanged lines hidden (view full) ---

787 .channels_max = 2,
788 .rates = WM8988_RATES,
789 .formats = WM8988_FORMATS,
790 },
791 .ops = &wm8988_ops,
792 .symmetric_rates = 1,
793};
794
795static int wm8988_probe(struct snd_soc_codec *codec)
795static int wm8988_probe(struct snd_soc_component *component)
796{
797 int ret = 0;
798
796{
797 int ret = 0;
798
799 ret = wm8988_reset(codec);
799 ret = wm8988_reset(component);
800 if (ret < 0) {
800 if (ret < 0) {
801 dev_err(codec->dev, "Failed to issue reset\n");
801 dev_err(component->dev, "Failed to issue reset\n");
802 return ret;
803 }
804
805 /* set the update bits (we always update left then right) */
802 return ret;
803 }
804
805 /* set the update bits (we always update left then right) */
806 snd_soc_update_bits(codec, WM8988_RADC, 0x0100, 0x0100);
807 snd_soc_update_bits(codec, WM8988_RDAC, 0x0100, 0x0100);
808 snd_soc_update_bits(codec, WM8988_ROUT1V, 0x0100, 0x0100);
809 snd_soc_update_bits(codec, WM8988_ROUT2V, 0x0100, 0x0100);
810 snd_soc_update_bits(codec, WM8988_RINVOL, 0x0100, 0x0100);
806 snd_soc_component_update_bits(component, WM8988_RADC, 0x0100, 0x0100);
807 snd_soc_component_update_bits(component, WM8988_RDAC, 0x0100, 0x0100);
808 snd_soc_component_update_bits(component, WM8988_ROUT1V, 0x0100, 0x0100);
809 snd_soc_component_update_bits(component, WM8988_ROUT2V, 0x0100, 0x0100);
810 snd_soc_component_update_bits(component, WM8988_RINVOL, 0x0100, 0x0100);
811
812 return 0;
813}
814
811
812 return 0;
813}
814
815static const struct snd_soc_codec_driver soc_codec_dev_wm8988 = {
816 .probe = wm8988_probe,
817 .set_bias_level = wm8988_set_bias_level,
818 .suspend_bias_off = true,
819
820 .component_driver = {
821 .controls = wm8988_snd_controls,
822 .num_controls = ARRAY_SIZE(wm8988_snd_controls),
823 .dapm_widgets = wm8988_dapm_widgets,
824 .num_dapm_widgets = ARRAY_SIZE(wm8988_dapm_widgets),
825 .dapm_routes = wm8988_dapm_routes,
826 .num_dapm_routes = ARRAY_SIZE(wm8988_dapm_routes),
827 },
815static const struct snd_soc_component_driver soc_component_dev_wm8988 = {
816 .probe = wm8988_probe,
817 .set_bias_level = wm8988_set_bias_level,
818 .controls = wm8988_snd_controls,
819 .num_controls = ARRAY_SIZE(wm8988_snd_controls),
820 .dapm_widgets = wm8988_dapm_widgets,
821 .num_dapm_widgets = ARRAY_SIZE(wm8988_dapm_widgets),
822 .dapm_routes = wm8988_dapm_routes,
823 .num_dapm_routes = ARRAY_SIZE(wm8988_dapm_routes),
824 .suspend_bias_off = 1,
825 .idle_bias_on = 1,
826 .use_pmdown_time = 1,
827 .endianness = 1,
828 .non_legacy_dai_naming = 1,
828};
829
830static const struct regmap_config wm8988_regmap = {
831 .reg_bits = 7,
832 .val_bits = 9,
833
834 .max_register = WM8988_LPPB,
835 .writeable_reg = wm8988_writeable,

--- 18 unchanged lines hidden (view full) ---

854 if (IS_ERR(wm8988->regmap)) {
855 ret = PTR_ERR(wm8988->regmap);
856 dev_err(&spi->dev, "Failed to init regmap: %d\n", ret);
857 return ret;
858 }
859
860 spi_set_drvdata(spi, wm8988);
861
829};
830
831static const struct regmap_config wm8988_regmap = {
832 .reg_bits = 7,
833 .val_bits = 9,
834
835 .max_register = WM8988_LPPB,
836 .writeable_reg = wm8988_writeable,

--- 18 unchanged lines hidden (view full) ---

855 if (IS_ERR(wm8988->regmap)) {
856 ret = PTR_ERR(wm8988->regmap);
857 dev_err(&spi->dev, "Failed to init regmap: %d\n", ret);
858 return ret;
859 }
860
861 spi_set_drvdata(spi, wm8988);
862
862 ret = snd_soc_register_codec(&spi->dev,
863 &soc_codec_dev_wm8988, &wm8988_dai, 1);
863 ret = devm_snd_soc_register_component(&spi->dev,
864 &soc_component_dev_wm8988, &wm8988_dai, 1);
864 return ret;
865}
866
865 return ret;
866}
867
867static int wm8988_spi_remove(struct spi_device *spi)
868{
869 snd_soc_unregister_codec(&spi->dev);
870 return 0;
871}
872
873static struct spi_driver wm8988_spi_driver = {
874 .driver = {
875 .name = "wm8988",
876 },
877 .probe = wm8988_spi_probe,
868static struct spi_driver wm8988_spi_driver = {
869 .driver = {
870 .name = "wm8988",
871 },
872 .probe = wm8988_spi_probe,
878 .remove = wm8988_spi_remove,
879};
880#endif /* CONFIG_SPI_MASTER */
881
882#if IS_ENABLED(CONFIG_I2C)
883static int wm8988_i2c_probe(struct i2c_client *i2c,
884 const struct i2c_device_id *id)
885{
886 struct wm8988_priv *wm8988;

--- 8 unchanged lines hidden (view full) ---

895
896 wm8988->regmap = devm_regmap_init_i2c(i2c, &wm8988_regmap);
897 if (IS_ERR(wm8988->regmap)) {
898 ret = PTR_ERR(wm8988->regmap);
899 dev_err(&i2c->dev, "Failed to init regmap: %d\n", ret);
900 return ret;
901 }
902
873};
874#endif /* CONFIG_SPI_MASTER */
875
876#if IS_ENABLED(CONFIG_I2C)
877static int wm8988_i2c_probe(struct i2c_client *i2c,
878 const struct i2c_device_id *id)
879{
880 struct wm8988_priv *wm8988;

--- 8 unchanged lines hidden (view full) ---

889
890 wm8988->regmap = devm_regmap_init_i2c(i2c, &wm8988_regmap);
891 if (IS_ERR(wm8988->regmap)) {
892 ret = PTR_ERR(wm8988->regmap);
893 dev_err(&i2c->dev, "Failed to init regmap: %d\n", ret);
894 return ret;
895 }
896
903 ret = snd_soc_register_codec(&i2c->dev,
904 &soc_codec_dev_wm8988, &wm8988_dai, 1);
897 ret = devm_snd_soc_register_component(&i2c->dev,
898 &soc_component_dev_wm8988, &wm8988_dai, 1);
905 return ret;
906}
907
899 return ret;
900}
901
908static int wm8988_i2c_remove(struct i2c_client *client)
909{
910 snd_soc_unregister_codec(&client->dev);
911 return 0;
912}
913
914static const struct i2c_device_id wm8988_i2c_id[] = {
915 { "wm8988", 0 },
916 { }
917};
918MODULE_DEVICE_TABLE(i2c, wm8988_i2c_id);
919
920static struct i2c_driver wm8988_i2c_driver = {
921 .driver = {
922 .name = "wm8988",
923 },
924 .probe = wm8988_i2c_probe,
902static const struct i2c_device_id wm8988_i2c_id[] = {
903 { "wm8988", 0 },
904 { }
905};
906MODULE_DEVICE_TABLE(i2c, wm8988_i2c_id);
907
908static struct i2c_driver wm8988_i2c_driver = {
909 .driver = {
910 .name = "wm8988",
911 },
912 .probe = wm8988_i2c_probe,
925 .remove = wm8988_i2c_remove,
926 .id_table = wm8988_i2c_id,
927};
928#endif
929
930static int __init wm8988_modinit(void)
931{
932 int ret = 0;
933#if IS_ENABLED(CONFIG_I2C)

--- 32 unchanged lines hidden ---
913 .id_table = wm8988_i2c_id,
914};
915#endif
916
917static int __init wm8988_modinit(void)
918{
919 int ret = 0;
920#if IS_ENABLED(CONFIG_I2C)

--- 32 unchanged lines hidden ---