aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/wm9713.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/codecs/wm9713.c')
-rw-r--r--sound/soc/codecs/wm9713.c79
1 files changed, 39 insertions, 40 deletions
diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c
index 1f241161445c..38d1fe0971fc 100644
--- a/sound/soc/codecs/wm9713.c
+++ b/sound/soc/codecs/wm9713.c
@@ -10,9 +10,6 @@
10 * Free Software Foundation; either version 2 of the License, or (at your 10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version. 11 * option) any later version.
12 * 12 *
13 * Revision history
14 * 4th Feb 2006 Initial version.
15 *
16 * Features:- 13 * Features:-
17 * 14 *
18 * o Support for AC97 Codec, Voice DAC and Aux DAC 15 * o Support for AC97 Codec, Voice DAC and Aux DAC
@@ -456,7 +453,7 @@ SND_SOC_DAPM_INPUT("MIC2B"),
456SND_SOC_DAPM_VMID("VMID"), 453SND_SOC_DAPM_VMID("VMID"),
457}; 454};
458 455
459static const char *audio_map[][3] = { 456static const struct snd_soc_dapm_route audio_map[] = {
460 /* left HP mixer */ 457 /* left HP mixer */
461 {"Left HP Mixer", "PC Beep Playback Switch", "PCBEEP"}, 458 {"Left HP Mixer", "PC Beep Playback Switch", "PCBEEP"},
462 {"Left HP Mixer", "Voice Playback Switch", "Voice DAC"}, 459 {"Left HP Mixer", "Voice Playback Switch", "Voice DAC"},
@@ -607,21 +604,14 @@ static const char *audio_map[][3] = {
607 {"Capture Mono Mux", "Stereo", "Capture Mixer"}, 604 {"Capture Mono Mux", "Stereo", "Capture Mixer"},
608 {"Capture Mono Mux", "Left", "Left Capture Source"}, 605 {"Capture Mono Mux", "Left", "Left Capture Source"},
609 {"Capture Mono Mux", "Right", "Right Capture Source"}, 606 {"Capture Mono Mux", "Right", "Right Capture Source"},
610
611 {NULL, NULL, NULL},
612}; 607};
613 608
614static int wm9713_add_widgets(struct snd_soc_codec *codec) 609static int wm9713_add_widgets(struct snd_soc_codec *codec)
615{ 610{
616 int i; 611 snd_soc_dapm_new_controls(codec, wm9713_dapm_widgets,
617 612 ARRAY_SIZE(wm9713_dapm_widgets));
618 for (i = 0; i < ARRAY_SIZE(wm9713_dapm_widgets); i++)
619 snd_soc_dapm_new_control(codec, &wm9713_dapm_widgets[i]);
620 613
621 /* set up audio path audio_mapnects */ 614 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
622 for (i = 0; audio_map[i][0] != NULL; i++)
623 snd_soc_dapm_connect_input(codec, audio_map[i][0],
624 audio_map[i][1], audio_map[i][2]);
625 615
626 snd_soc_dapm_new_widgets(codec); 616 snd_soc_dapm_new_widgets(codec);
627 return 0; 617 return 0;
@@ -799,7 +789,7 @@ static int wm9713_set_pll(struct snd_soc_codec *codec,
799 return 0; 789 return 0;
800} 790}
801 791
802static int wm9713_set_dai_pll(struct snd_soc_codec_dai *codec_dai, 792static int wm9713_set_dai_pll(struct snd_soc_dai *codec_dai,
803 int pll_id, unsigned int freq_in, unsigned int freq_out) 793 int pll_id, unsigned int freq_in, unsigned int freq_out)
804{ 794{
805 struct snd_soc_codec *codec = codec_dai->codec; 795 struct snd_soc_codec *codec = codec_dai->codec;
@@ -810,7 +800,7 @@ static int wm9713_set_dai_pll(struct snd_soc_codec_dai *codec_dai,
810 * Tristate the PCM DAI lines, tristate can be disabled by calling 800 * Tristate the PCM DAI lines, tristate can be disabled by calling
811 * wm9713_set_dai_fmt() 801 * wm9713_set_dai_fmt()
812 */ 802 */
813static int wm9713_set_dai_tristate(struct snd_soc_codec_dai *codec_dai, 803static int wm9713_set_dai_tristate(struct snd_soc_dai *codec_dai,
814 int tristate) 804 int tristate)
815{ 805{
816 struct snd_soc_codec *codec = codec_dai->codec; 806 struct snd_soc_codec *codec = codec_dai->codec;
@@ -826,7 +816,7 @@ static int wm9713_set_dai_tristate(struct snd_soc_codec_dai *codec_dai,
826 * Configure WM9713 clock dividers. 816 * Configure WM9713 clock dividers.
827 * Voice DAC needs 256 FS 817 * Voice DAC needs 256 FS
828 */ 818 */
829static int wm9713_set_dai_clkdiv(struct snd_soc_codec_dai *codec_dai, 819static int wm9713_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
830 int div_id, int div) 820 int div_id, int div)
831{ 821{
832 struct snd_soc_codec *codec = codec_dai->codec; 822 struct snd_soc_codec *codec = codec_dai->codec;
@@ -868,7 +858,7 @@ static int wm9713_set_dai_clkdiv(struct snd_soc_codec_dai *codec_dai,
868 return 0; 858 return 0;
869} 859}
870 860
871static int wm9713_set_dai_fmt(struct snd_soc_codec_dai *codec_dai, 861static int wm9713_set_dai_fmt(struct snd_soc_dai *codec_dai,
872 unsigned int fmt) 862 unsigned int fmt)
873{ 863{
874 struct snd_soc_codec *codec = codec_dai->codec; 864 struct snd_soc_codec *codec = codec_dai->codec;
@@ -886,7 +876,7 @@ static int wm9713_set_dai_fmt(struct snd_soc_codec_dai *codec_dai,
886 gpio |= 0x0018; 876 gpio |= 0x0018;
887 break; 877 break;
888 case SND_SOC_DAIFMT_CBS_CFS: 878 case SND_SOC_DAIFMT_CBS_CFS:
889 reg |= 0x0200; 879 reg |= 0x2000;
890 gpio |= 0x001a; 880 gpio |= 0x001a;
891 break; 881 break;
892 case SND_SOC_DAIFMT_CBS_CFM: 882 case SND_SOC_DAIFMT_CBS_CFM:
@@ -1011,15 +1001,24 @@ static int ac97_aux_prepare(struct snd_pcm_substream *substream)
1011 return ac97_write(codec, AC97_PCM_SURR_DAC_RATE, runtime->rate); 1001 return ac97_write(codec, AC97_PCM_SURR_DAC_RATE, runtime->rate);
1012} 1002}
1013 1003
1014#define WM9713_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ 1004#define WM9713_RATES (SNDRV_PCM_RATE_8000 | \
1015 SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 |\ 1005 SNDRV_PCM_RATE_11025 | \
1016 SNDRV_PCM_RATE_48000) 1006 SNDRV_PCM_RATE_22050 | \
1007 SNDRV_PCM_RATE_44100 | \
1008 SNDRV_PCM_RATE_48000)
1009
1010#define WM9713_PCM_RATES (SNDRV_PCM_RATE_8000 | \
1011 SNDRV_PCM_RATE_11025 | \
1012 SNDRV_PCM_RATE_16000 | \
1013 SNDRV_PCM_RATE_22050 | \
1014 SNDRV_PCM_RATE_44100 | \
1015 SNDRV_PCM_RATE_48000)
1017 1016
1018#define WM9713_PCM_FORMATS \ 1017#define WM9713_PCM_FORMATS \
1019 (SNDRV_PCM_FORMAT_S16_LE | SNDRV_PCM_FORMAT_S20_3LE | \ 1018 (SNDRV_PCM_FORMAT_S16_LE | SNDRV_PCM_FORMAT_S20_3LE | \
1020 SNDRV_PCM_FORMAT_S24_LE) 1019 SNDRV_PCM_FORMAT_S24_LE)
1021 1020
1022struct snd_soc_codec_dai wm9713_dai[] = { 1021struct snd_soc_dai wm9713_dai[] = {
1023{ 1022{
1024 .name = "AC97 HiFi", 1023 .name = "AC97 HiFi",
1025 .type = SND_SOC_DAI_AC97_BUS, 1024 .type = SND_SOC_DAI_AC97_BUS,
@@ -1061,13 +1060,13 @@ struct snd_soc_codec_dai wm9713_dai[] = {
1061 .stream_name = "Voice Playback", 1060 .stream_name = "Voice Playback",
1062 .channels_min = 1, 1061 .channels_min = 1,
1063 .channels_max = 1, 1062 .channels_max = 1,
1064 .rates = WM9713_RATES, 1063 .rates = WM9713_PCM_RATES,
1065 .formats = WM9713_PCM_FORMATS,}, 1064 .formats = WM9713_PCM_FORMATS,},
1066 .capture = { 1065 .capture = {
1067 .stream_name = "Voice Capture", 1066 .stream_name = "Voice Capture",
1068 .channels_min = 1, 1067 .channels_min = 1,
1069 .channels_max = 2, 1068 .channels_max = 2,
1070 .rates = WM9713_RATES, 1069 .rates = WM9713_PCM_RATES,
1071 .formats = WM9713_PCM_FORMATS,}, 1070 .formats = WM9713_PCM_FORMATS,},
1072 .ops = { 1071 .ops = {
1073 .hw_params = wm9713_pcm_hw_params, 1072 .hw_params = wm9713_pcm_hw_params,
@@ -1086,44 +1085,44 @@ int wm9713_reset(struct snd_soc_codec *codec, int try_warm)
1086{ 1085{
1087 if (try_warm && soc_ac97_ops.warm_reset) { 1086 if (try_warm && soc_ac97_ops.warm_reset) {
1088 soc_ac97_ops.warm_reset(codec->ac97); 1087 soc_ac97_ops.warm_reset(codec->ac97);
1089 if (!(ac97_read(codec, 0) & 0x8000)) 1088 if (ac97_read(codec, 0) == wm9713_reg[0])
1090 return 1; 1089 return 1;
1091 } 1090 }
1092 1091
1093 soc_ac97_ops.reset(codec->ac97); 1092 soc_ac97_ops.reset(codec->ac97);
1094 if (ac97_read(codec, 0) & 0x8000) 1093 if (ac97_read(codec, 0) != wm9713_reg[0])
1095 return -EIO; 1094 return -EIO;
1096 return 0; 1095 return 0;
1097} 1096}
1098EXPORT_SYMBOL_GPL(wm9713_reset); 1097EXPORT_SYMBOL_GPL(wm9713_reset);
1099 1098
1100static int wm9713_dapm_event(struct snd_soc_codec *codec, int event) 1099static int wm9713_set_bias_level(struct snd_soc_codec *codec,
1100 enum snd_soc_bias_level level)
1101{ 1101{
1102 u16 reg; 1102 u16 reg;
1103 1103
1104 switch (event) { 1104 switch (level) {
1105 case SNDRV_CTL_POWER_D0: /* full On */ 1105 case SND_SOC_BIAS_ON:
1106 /* enable thermal shutdown */ 1106 /* enable thermal shutdown */
1107 reg = ac97_read(codec, AC97_EXTENDED_MID) & 0x1bff; 1107 reg = ac97_read(codec, AC97_EXTENDED_MID) & 0x1bff;
1108 ac97_write(codec, AC97_EXTENDED_MID, reg); 1108 ac97_write(codec, AC97_EXTENDED_MID, reg);
1109 break; 1109 break;
1110 case SNDRV_CTL_POWER_D1: /* partial On */ 1110 case SND_SOC_BIAS_PREPARE:
1111 case SNDRV_CTL_POWER_D2: /* partial On */
1112 break; 1111 break;
1113 case SNDRV_CTL_POWER_D3hot: /* Off, with power */ 1112 case SND_SOC_BIAS_STANDBY:
1114 /* enable master bias and vmid */ 1113 /* enable master bias and vmid */
1115 reg = ac97_read(codec, AC97_EXTENDED_MID) & 0x3bff; 1114 reg = ac97_read(codec, AC97_EXTENDED_MID) & 0x3bff;
1116 ac97_write(codec, AC97_EXTENDED_MID, reg); 1115 ac97_write(codec, AC97_EXTENDED_MID, reg);
1117 ac97_write(codec, AC97_POWERDOWN, 0x0000); 1116 ac97_write(codec, AC97_POWERDOWN, 0x0000);
1118 break; 1117 break;
1119 case SNDRV_CTL_POWER_D3cold: /* Off, without power */ 1118 case SND_SOC_BIAS_OFF:
1120 /* disable everything including AC link */ 1119 /* disable everything including AC link */
1121 ac97_write(codec, AC97_EXTENDED_MID, 0xffff); 1120 ac97_write(codec, AC97_EXTENDED_MID, 0xffff);
1122 ac97_write(codec, AC97_EXTENDED_MSTATUS, 0xffff); 1121 ac97_write(codec, AC97_EXTENDED_MSTATUS, 0xffff);
1123 ac97_write(codec, AC97_POWERDOWN, 0xffff); 1122 ac97_write(codec, AC97_POWERDOWN, 0xffff);
1124 break; 1123 break;
1125 } 1124 }
1126 codec->dapm_state = event; 1125 codec->bias_level = level;
1127 return 0; 1126 return 0;
1128} 1127}
1129 1128
@@ -1160,7 +1159,7 @@ static int wm9713_soc_resume(struct platform_device *pdev)
1160 return ret; 1159 return ret;
1161 } 1160 }
1162 1161
1163 wm9713_dapm_event(codec, SNDRV_CTL_POWER_D3hot); 1162 wm9713_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1164 1163
1165 /* do we need to re-start the PLL ? */ 1164 /* do we need to re-start the PLL ? */
1166 if (wm9713->pll_out) 1165 if (wm9713->pll_out)
@@ -1176,8 +1175,8 @@ static int wm9713_soc_resume(struct platform_device *pdev)
1176 } 1175 }
1177 } 1176 }
1178 1177
1179 if (codec->suspend_dapm_state == SNDRV_CTL_POWER_D0) 1178 if (codec->suspend_bias_level == SND_SOC_BIAS_ON)
1180 wm9713_dapm_event(codec, SNDRV_CTL_POWER_D0); 1179 wm9713_set_bias_level(codec, SND_SOC_BIAS_ON);
1181 1180
1182 return ret; 1181 return ret;
1183} 1182}
@@ -1216,7 +1215,7 @@ static int wm9713_soc_probe(struct platform_device *pdev)
1216 codec->num_dai = ARRAY_SIZE(wm9713_dai); 1215 codec->num_dai = ARRAY_SIZE(wm9713_dai);
1217 codec->write = ac97_write; 1216 codec->write = ac97_write;
1218 codec->read = ac97_read; 1217 codec->read = ac97_read;
1219 codec->dapm_event = wm9713_dapm_event; 1218 codec->set_bias_level = wm9713_set_bias_level;
1220 INIT_LIST_HEAD(&codec->dapm_widgets); 1219 INIT_LIST_HEAD(&codec->dapm_widgets);
1221 INIT_LIST_HEAD(&codec->dapm_paths); 1220 INIT_LIST_HEAD(&codec->dapm_paths);
1222 1221
@@ -1238,7 +1237,7 @@ static int wm9713_soc_probe(struct platform_device *pdev)
1238 goto reset_err; 1237 goto reset_err;
1239 } 1238 }
1240 1239
1241 wm9713_dapm_event(codec, SNDRV_CTL_POWER_D3hot); 1240 wm9713_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1242 1241
1243 /* unmute the adc - move to kcontrol */ 1242 /* unmute the adc - move to kcontrol */
1244 reg = ac97_read(codec, AC97_CD) & 0x7fff; 1243 reg = ac97_read(codec, AC97_CD) & 0x7fff;