aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/wm8350.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/codecs/wm8350.c')
-rw-r--r--sound/soc/codecs/wm8350.c51
1 files changed, 44 insertions, 7 deletions
diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c
index e7348d341b76..3ff0373dff89 100644
--- a/sound/soc/codecs/wm8350.c
+++ b/sound/soc/codecs/wm8350.c
@@ -63,6 +63,8 @@ struct wm8350_data {
63 struct wm8350_jack_data hpl; 63 struct wm8350_jack_data hpl;
64 struct wm8350_jack_data hpr; 64 struct wm8350_jack_data hpr;
65 struct regulator_bulk_data supplies[ARRAY_SIZE(supply_names)]; 65 struct regulator_bulk_data supplies[ARRAY_SIZE(supply_names)];
66 int fll_freq_out;
67 int fll_freq_in;
66}; 68};
67 69
68static unsigned int wm8350_codec_cache_read(struct snd_soc_codec *codec, 70static unsigned int wm8350_codec_cache_read(struct snd_soc_codec *codec,
@@ -406,7 +408,6 @@ static const char *wm8350_deemp[] = { "None", "32kHz", "44.1kHz", "48kHz" };
406static const char *wm8350_pol[] = { "Normal", "Inv R", "Inv L", "Inv L & R" }; 408static const char *wm8350_pol[] = { "Normal", "Inv R", "Inv L", "Inv L & R" };
407static const char *wm8350_dacmutem[] = { "Normal", "Soft" }; 409static const char *wm8350_dacmutem[] = { "Normal", "Soft" };
408static const char *wm8350_dacmutes[] = { "Fast", "Slow" }; 410static const char *wm8350_dacmutes[] = { "Fast", "Slow" };
409static const char *wm8350_dacfilter[] = { "Normal", "Sloping" };
410static const char *wm8350_adcfilter[] = { "None", "High Pass" }; 411static const char *wm8350_adcfilter[] = { "None", "High Pass" };
411static const char *wm8350_adchp[] = { "44.1kHz", "8kHz", "16kHz", "32kHz" }; 412static const char *wm8350_adchp[] = { "44.1kHz", "8kHz", "16kHz", "32kHz" };
412static const char *wm8350_lr[] = { "Left", "Right" }; 413static const char *wm8350_lr[] = { "Left", "Right" };
@@ -416,7 +417,6 @@ static const struct soc_enum wm8350_enum[] = {
416 SOC_ENUM_SINGLE(WM8350_DAC_CONTROL, 0, 4, wm8350_pol), 417 SOC_ENUM_SINGLE(WM8350_DAC_CONTROL, 0, 4, wm8350_pol),
417 SOC_ENUM_SINGLE(WM8350_DAC_MUTE_VOLUME, 14, 2, wm8350_dacmutem), 418 SOC_ENUM_SINGLE(WM8350_DAC_MUTE_VOLUME, 14, 2, wm8350_dacmutem),
418 SOC_ENUM_SINGLE(WM8350_DAC_MUTE_VOLUME, 13, 2, wm8350_dacmutes), 419 SOC_ENUM_SINGLE(WM8350_DAC_MUTE_VOLUME, 13, 2, wm8350_dacmutes),
419 SOC_ENUM_SINGLE(WM8350_DAC_MUTE_VOLUME, 12, 2, wm8350_dacfilter),
420 SOC_ENUM_SINGLE(WM8350_ADC_CONTROL, 15, 2, wm8350_adcfilter), 420 SOC_ENUM_SINGLE(WM8350_ADC_CONTROL, 15, 2, wm8350_adcfilter),
421 SOC_ENUM_SINGLE(WM8350_ADC_CONTROL, 8, 4, wm8350_adchp), 421 SOC_ENUM_SINGLE(WM8350_ADC_CONTROL, 8, 4, wm8350_adchp),
422 SOC_ENUM_SINGLE(WM8350_ADC_CONTROL, 0, 4, wm8350_pol), 422 SOC_ENUM_SINGLE(WM8350_ADC_CONTROL, 0, 4, wm8350_pol),
@@ -444,10 +444,9 @@ static const struct snd_kcontrol_new wm8350_snd_controls[] = {
444 0, 255, 0, dac_pcm_tlv), 444 0, 255, 0, dac_pcm_tlv),
445 SOC_ENUM("Playback PCM Mute Function", wm8350_enum[2]), 445 SOC_ENUM("Playback PCM Mute Function", wm8350_enum[2]),
446 SOC_ENUM("Playback PCM Mute Speed", wm8350_enum[3]), 446 SOC_ENUM("Playback PCM Mute Speed", wm8350_enum[3]),
447 SOC_ENUM("Playback PCM Filter", wm8350_enum[4]), 447 SOC_ENUM("Capture PCM Filter", wm8350_enum[4]),
448 SOC_ENUM("Capture PCM Filter", wm8350_enum[5]), 448 SOC_ENUM("Capture PCM HP Filter", wm8350_enum[5]),
449 SOC_ENUM("Capture PCM HP Filter", wm8350_enum[6]), 449 SOC_ENUM("Capture ADC Inversion", wm8350_enum[6]),
450 SOC_ENUM("Capture ADC Inversion", wm8350_enum[7]),
451 SOC_WM8350_DOUBLE_R_TLV("Capture PCM Volume", 450 SOC_WM8350_DOUBLE_R_TLV("Capture PCM Volume",
452 WM8350_ADC_DIGITAL_VOLUME_L, 451 WM8350_ADC_DIGITAL_VOLUME_L,
453 WM8350_ADC_DIGITAL_VOLUME_R, 452 WM8350_ADC_DIGITAL_VOLUME_R,
@@ -613,7 +612,7 @@ SOC_DAPM_SINGLE("Switch", WM8350_BEEP_VOLUME, 15, 1, 1);
613 612
614/* Out4 Capture Mux */ 613/* Out4 Capture Mux */
615static const struct snd_kcontrol_new wm8350_out4_capture_controls = 614static const struct snd_kcontrol_new wm8350_out4_capture_controls =
616SOC_DAPM_ENUM("Route", wm8350_enum[8]); 615SOC_DAPM_ENUM("Route", wm8350_enum[7]);
617 616
618static const struct snd_soc_dapm_widget wm8350_dapm_widgets[] = { 617static const struct snd_soc_dapm_widget wm8350_dapm_widgets[] = {
619 618
@@ -993,6 +992,7 @@ static int wm8350_pcm_hw_params(struct snd_pcm_substream *substream,
993 struct snd_soc_dai *codec_dai) 992 struct snd_soc_dai *codec_dai)
994{ 993{
995 struct snd_soc_codec *codec = codec_dai->codec; 994 struct snd_soc_codec *codec = codec_dai->codec;
995 struct wm8350 *wm8350 = codec->control_data;
996 u16 iface = wm8350_codec_read(codec, WM8350_AI_FORMATING) & 996 u16 iface = wm8350_codec_read(codec, WM8350_AI_FORMATING) &
997 ~WM8350_AIF_WL_MASK; 997 ~WM8350_AIF_WL_MASK;
998 998
@@ -1012,6 +1012,19 @@ static int wm8350_pcm_hw_params(struct snd_pcm_substream *substream,
1012 } 1012 }
1013 1013
1014 wm8350_codec_write(codec, WM8350_AI_FORMATING, iface); 1014 wm8350_codec_write(codec, WM8350_AI_FORMATING, iface);
1015
1016 /* The sloping stopband filter is recommended for use with
1017 * lower sample rates to improve performance.
1018 */
1019 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
1020 if (params_rate(params) < 24000)
1021 wm8350_set_bits(wm8350, WM8350_DAC_MUTE_VOLUME,
1022 WM8350_DAC_SB_FILT);
1023 else
1024 wm8350_clear_bits(wm8350, WM8350_DAC_MUTE_VOLUME,
1025 WM8350_DAC_SB_FILT);
1026 }
1027
1015 return 0; 1028 return 0;
1016} 1029}
1017 1030
@@ -1093,10 +1106,14 @@ static int wm8350_set_fll(struct snd_soc_dai *codec_dai,
1093{ 1106{
1094 struct snd_soc_codec *codec = codec_dai->codec; 1107 struct snd_soc_codec *codec = codec_dai->codec;
1095 struct wm8350 *wm8350 = codec->control_data; 1108 struct wm8350 *wm8350 = codec->control_data;
1109 struct wm8350_data *priv = codec->private_data;
1096 struct _fll_div fll_div; 1110 struct _fll_div fll_div;
1097 int ret = 0; 1111 int ret = 0;
1098 u16 fll_1, fll_4; 1112 u16 fll_1, fll_4;
1099 1113
1114 if (freq_in == priv->fll_freq_in && freq_out == priv->fll_freq_out)
1115 return 0;
1116
1100 /* power down FLL - we need to do this for reconfiguration */ 1117 /* power down FLL - we need to do this for reconfiguration */
1101 wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_4, 1118 wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_4,
1102 WM8350_FLL_ENA | WM8350_FLL_OSC_ENA); 1119 WM8350_FLL_ENA | WM8350_FLL_OSC_ENA);
@@ -1131,6 +1148,9 @@ static int wm8350_set_fll(struct snd_soc_dai *codec_dai,
1131 wm8350_set_bits(wm8350, WM8350_POWER_MGMT_4, WM8350_FLL_OSC_ENA); 1148 wm8350_set_bits(wm8350, WM8350_POWER_MGMT_4, WM8350_FLL_OSC_ENA);
1132 wm8350_set_bits(wm8350, WM8350_POWER_MGMT_4, WM8350_FLL_ENA); 1149 wm8350_set_bits(wm8350, WM8350_POWER_MGMT_4, WM8350_FLL_ENA);
1133 1150
1151 priv->fll_freq_out = freq_out;
1152 priv->fll_freq_in = freq_in;
1153
1134 return 0; 1154 return 0;
1135} 1155}
1136 1156
@@ -1660,6 +1680,21 @@ static int __devexit wm8350_codec_remove(struct platform_device *pdev)
1660 return 0; 1680 return 0;
1661} 1681}
1662 1682
1683#ifdef CONFIG_PM
1684static int wm8350_codec_suspend(struct platform_device *pdev, pm_message_t m)
1685{
1686 return snd_soc_suspend_device(&pdev->dev);
1687}
1688
1689static int wm8350_codec_resume(struct platform_device *pdev)
1690{
1691 return snd_soc_resume_device(&pdev->dev);
1692}
1693#else
1694#define wm8350_codec_suspend NULL
1695#define wm8350_codec_resume NULL
1696#endif
1697
1663static struct platform_driver wm8350_codec_driver = { 1698static struct platform_driver wm8350_codec_driver = {
1664 .driver = { 1699 .driver = {
1665 .name = "wm8350-codec", 1700 .name = "wm8350-codec",
@@ -1667,6 +1702,8 @@ static struct platform_driver wm8350_codec_driver = {
1667 }, 1702 },
1668 .probe = wm8350_codec_probe, 1703 .probe = wm8350_codec_probe,
1669 .remove = __devexit_p(wm8350_codec_remove), 1704 .remove = __devexit_p(wm8350_codec_remove),
1705 .suspend = wm8350_codec_suspend,
1706 .resume = wm8350_codec_resume,
1670}; 1707};
1671 1708
1672static __init int wm8350_init(void) 1709static __init int wm8350_init(void)