diff options
Diffstat (limited to 'sound/soc/codecs/wm8350.c')
-rw-r--r-- | sound/soc/codecs/wm8350.c | 51 |
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 | ||
68 | static unsigned int wm8350_codec_cache_read(struct snd_soc_codec *codec, | 70 | static 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" }; | |||
406 | static const char *wm8350_pol[] = { "Normal", "Inv R", "Inv L", "Inv L & R" }; | 408 | static const char *wm8350_pol[] = { "Normal", "Inv R", "Inv L", "Inv L & R" }; |
407 | static const char *wm8350_dacmutem[] = { "Normal", "Soft" }; | 409 | static const char *wm8350_dacmutem[] = { "Normal", "Soft" }; |
408 | static const char *wm8350_dacmutes[] = { "Fast", "Slow" }; | 410 | static const char *wm8350_dacmutes[] = { "Fast", "Slow" }; |
409 | static const char *wm8350_dacfilter[] = { "Normal", "Sloping" }; | ||
410 | static const char *wm8350_adcfilter[] = { "None", "High Pass" }; | 411 | static const char *wm8350_adcfilter[] = { "None", "High Pass" }; |
411 | static const char *wm8350_adchp[] = { "44.1kHz", "8kHz", "16kHz", "32kHz" }; | 412 | static const char *wm8350_adchp[] = { "44.1kHz", "8kHz", "16kHz", "32kHz" }; |
412 | static const char *wm8350_lr[] = { "Left", "Right" }; | 413 | static 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 */ |
615 | static const struct snd_kcontrol_new wm8350_out4_capture_controls = | 614 | static const struct snd_kcontrol_new wm8350_out4_capture_controls = |
616 | SOC_DAPM_ENUM("Route", wm8350_enum[8]); | 615 | SOC_DAPM_ENUM("Route", wm8350_enum[7]); |
617 | 616 | ||
618 | static const struct snd_soc_dapm_widget wm8350_dapm_widgets[] = { | 617 | static 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 | ||
1684 | static int wm8350_codec_suspend(struct platform_device *pdev, pm_message_t m) | ||
1685 | { | ||
1686 | return snd_soc_suspend_device(&pdev->dev); | ||
1687 | } | ||
1688 | |||
1689 | static 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 | |||
1663 | static struct platform_driver wm8350_codec_driver = { | 1698 | static 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 | ||
1672 | static __init int wm8350_init(void) | 1709 | static __init int wm8350_init(void) |