diff options
Diffstat (limited to 'sound/soc/codecs/wm9713.c')
-rw-r--r-- | sound/soc/codecs/wm9713.c | 79 |
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"), | |||
456 | SND_SOC_DAPM_VMID("VMID"), | 453 | SND_SOC_DAPM_VMID("VMID"), |
457 | }; | 454 | }; |
458 | 455 | ||
459 | static const char *audio_map[][3] = { | 456 | static 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 | ||
614 | static int wm9713_add_widgets(struct snd_soc_codec *codec) | 609 | static 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 | ||
802 | static int wm9713_set_dai_pll(struct snd_soc_codec_dai *codec_dai, | 792 | static 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 | */ |
813 | static int wm9713_set_dai_tristate(struct snd_soc_codec_dai *codec_dai, | 803 | static 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 | */ |
829 | static int wm9713_set_dai_clkdiv(struct snd_soc_codec_dai *codec_dai, | 819 | static 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 | ||
871 | static int wm9713_set_dai_fmt(struct snd_soc_codec_dai *codec_dai, | 861 | static 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 | ||
1022 | struct snd_soc_codec_dai wm9713_dai[] = { | 1021 | struct 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 | } |
1098 | EXPORT_SYMBOL_GPL(wm9713_reset); | 1097 | EXPORT_SYMBOL_GPL(wm9713_reset); |
1099 | 1098 | ||
1100 | static int wm9713_dapm_event(struct snd_soc_codec *codec, int event) | 1099 | static 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; |