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.c230
1 files changed, 131 insertions, 99 deletions
diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c
index bddee30a4bc7..5df7f6d12bef 100644
--- a/sound/soc/codecs/wm9713.c
+++ b/sound/soc/codecs/wm9713.c
@@ -30,7 +30,10 @@
30#include "wm9713.h" 30#include "wm9713.h"
31 31
32struct wm9713_priv { 32struct wm9713_priv {
33 struct snd_ac97 *ac97;
33 u32 pll_in; /* PLL input frequency */ 34 u32 pll_in; /* PLL input frequency */
35 unsigned int hp_mixer[2];
36 struct mutex lock;
34}; 37};
35 38
36static unsigned int ac97_read(struct snd_soc_codec *codec, 39static unsigned int ac97_read(struct snd_soc_codec *codec,
@@ -59,13 +62,10 @@ static const u16 wm9713_reg[] = {
59 0x0000, 0x0000, 0x0000, 0x0000, 62 0x0000, 0x0000, 0x0000, 0x0000,
60 0x0000, 0x0000, 0x0000, 0x0006, 63 0x0000, 0x0000, 0x0000, 0x0006,
61 0x0001, 0x0000, 0x574d, 0x4c13, 64 0x0001, 0x0000, 0x574d, 0x4c13,
62 0x0000, 0x0000, 0x0000
63}; 65};
64 66
65/* virtual HP mixers regs */ 67#define HPL_MIXER 0
66#define HPL_MIXER 0x80 68#define HPR_MIXER 1
67#define HPR_MIXER 0x82
68#define MICB_MUX 0x82
69 69
70static const char *wm9713_mic_mixer[] = {"Stereo", "Mic 1", "Mic 2", "Mute"}; 70static const char *wm9713_mic_mixer[] = {"Stereo", "Mic 1", "Mic 2", "Mute"};
71static const char *wm9713_rec_mux[] = {"Stereo", "Left", "Right", "Mute"}; 71static const char *wm9713_rec_mux[] = {"Stereo", "Left", "Right", "Mute"};
@@ -110,7 +110,7 @@ SOC_ENUM_SINGLE(AC97_REC_GAIN_MIC, 10, 8, wm9713_dac_inv), /* dac invert 2 15 */
110SOC_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 15, 2, wm9713_bass), /* bass control 16 */ 110SOC_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 15, 2, wm9713_bass), /* bass control 16 */
111SOC_ENUM_SINGLE(AC97_PCI_SVID, 5, 2, wm9713_ng_type), /* noise gate type 17 */ 111SOC_ENUM_SINGLE(AC97_PCI_SVID, 5, 2, wm9713_ng_type), /* noise gate type 17 */
112SOC_ENUM_SINGLE(AC97_3D_CONTROL, 12, 3, wm9713_mic_select), /* mic selection 18 */ 112SOC_ENUM_SINGLE(AC97_3D_CONTROL, 12, 3, wm9713_mic_select), /* mic selection 18 */
113SOC_ENUM_SINGLE(MICB_MUX, 0, 2, wm9713_micb_select), /* mic selection 19 */ 113SOC_ENUM_SINGLE_VIRT(2, wm9713_micb_select), /* mic selection 19 */
114}; 114};
115 115
116static const DECLARE_TLV_DB_SCALE(out_tlv, -4650, 150, 0); 116static const DECLARE_TLV_DB_SCALE(out_tlv, -4650, 150, 0);
@@ -234,6 +234,14 @@ static int wm9713_voice_shutdown(struct snd_soc_dapm_widget *w,
234 return 0; 234 return 0;
235} 235}
236 236
237static const unsigned int wm9713_mixer_mute_regs[] = {
238 AC97_PC_BEEP,
239 AC97_MASTER_TONE,
240 AC97_PHONE,
241 AC97_REC_SEL,
242 AC97_PCM,
243 AC97_AUX,
244};
237 245
238/* We have to create a fake left and right HP mixers because 246/* We have to create a fake left and right HP mixers because
239 * the codec only has a single control that is shared by both channels. 247 * the codec only has a single control that is shared by both channels.
@@ -241,73 +249,95 @@ static int wm9713_voice_shutdown(struct snd_soc_dapm_widget *w,
241 * register map, thus we add a new (virtual) register to help determine the 249 * register map, thus we add a new (virtual) register to help determine the
242 * audio route within the device. 250 * audio route within the device.
243 */ 251 */
244static int mixer_event(struct snd_soc_dapm_widget *w, 252static int wm9713_hp_mixer_put(struct snd_kcontrol *kcontrol,
245 struct snd_kcontrol *kcontrol, int event) 253 struct snd_ctl_elem_value *ucontrol)
246{ 254{
247 u16 l, r, beep, tone, phone, rec, pcm, aux; 255 struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol);
248 256 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(dapm);
249 l = ac97_read(w->codec, HPL_MIXER); 257 struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec);
250 r = ac97_read(w->codec, HPR_MIXER); 258 unsigned int val = ucontrol->value.enumerated.item[0];
251 beep = ac97_read(w->codec, AC97_PC_BEEP); 259 struct soc_mixer_control *mc =
252 tone = ac97_read(w->codec, AC97_MASTER_TONE); 260 (struct soc_mixer_control *)kcontrol->private_value;
253 phone = ac97_read(w->codec, AC97_PHONE); 261 unsigned int mixer, mask, shift, old;
254 rec = ac97_read(w->codec, AC97_REC_SEL); 262 struct snd_soc_dapm_update update;
255 pcm = ac97_read(w->codec, AC97_PCM); 263 bool change;
256 aux = ac97_read(w->codec, AC97_AUX); 264
257 265 mixer = mc->shift >> 8;
258 if (event & SND_SOC_DAPM_PRE_REG) 266 shift = mc->shift & 0xff;
259 return 0; 267 mask = (1 << shift);
260 if ((l & 0x1) || (r & 0x1)) 268
261 ac97_write(w->codec, AC97_PC_BEEP, beep & 0x7fff); 269 mutex_lock(&wm9713->lock);
270 old = wm9713->hp_mixer[mixer];
271 if (ucontrol->value.enumerated.item[0])
272 wm9713->hp_mixer[mixer] |= mask;
262 else 273 else
263 ac97_write(w->codec, AC97_PC_BEEP, beep | 0x8000); 274 wm9713->hp_mixer[mixer] &= ~mask;
275
276 change = old != wm9713->hp_mixer[mixer];
277 if (change) {
278 update.kcontrol = kcontrol;
279 update.reg = wm9713_mixer_mute_regs[shift];
280 update.mask = 0x8000;
281 if ((wm9713->hp_mixer[0] & mask) ||
282 (wm9713->hp_mixer[1] & mask))
283 update.val = 0x0;
284 else
285 update.val = 0x8000;
286
287 snd_soc_dapm_mixer_update_power(dapm, kcontrol, val,
288 &update);
289 }
264 290
265 if ((l & 0x2) || (r & 0x2)) 291 mutex_unlock(&wm9713->lock);
266 ac97_write(w->codec, AC97_MASTER_TONE, tone & 0x7fff);
267 else
268 ac97_write(w->codec, AC97_MASTER_TONE, tone | 0x8000);
269 292
270 if ((l & 0x4) || (r & 0x4)) 293 return change;
271 ac97_write(w->codec, AC97_PHONE, phone & 0x7fff); 294}
272 else
273 ac97_write(w->codec, AC97_PHONE, phone | 0x8000);
274 295
275 if ((l & 0x8) || (r & 0x8)) 296static int wm9713_hp_mixer_get(struct snd_kcontrol *kcontrol,
276 ac97_write(w->codec, AC97_REC_SEL, rec & 0x7fff); 297 struct snd_ctl_elem_value *ucontrol)
277 else 298{
278 ac97_write(w->codec, AC97_REC_SEL, rec | 0x8000); 299 struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol);
300 struct snd_soc_codec *codec = snd_soc_dapm_to_codec(dapm);
301 struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec);
302 struct soc_mixer_control *mc =
303 (struct soc_mixer_control *)kcontrol->private_value;
304 unsigned int mixer, shift;
279 305
280 if ((l & 0x10) || (r & 0x10)) 306 mixer = mc->shift >> 8;
281 ac97_write(w->codec, AC97_PCM, pcm & 0x7fff); 307 shift = mc->shift & 0xff;
282 else
283 ac97_write(w->codec, AC97_PCM, pcm | 0x8000);
284 308
285 if ((l & 0x20) || (r & 0x20)) 309 ucontrol->value.enumerated.item[0] =
286 ac97_write(w->codec, AC97_AUX, aux & 0x7fff); 310 (wm9713->hp_mixer[mixer] >> shift) & 1;
287 else
288 ac97_write(w->codec, AC97_AUX, aux | 0x8000);
289 311
290 return 0; 312 return 0;
291} 313}
292 314
315#define WM9713_HP_MIXER_CTRL(xname, xmixer, xshift) { \
316 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
317 .info = snd_soc_info_volsw, \
318 .get = wm9713_hp_mixer_get, .put = wm9713_hp_mixer_put, \
319 .private_value = SOC_DOUBLE_VALUE(SND_SOC_NOPM, \
320 xshift, xmixer, 1, 0, 0) \
321}
322
293/* Left Headphone Mixers */ 323/* Left Headphone Mixers */
294static const struct snd_kcontrol_new wm9713_hpl_mixer_controls[] = { 324static const struct snd_kcontrol_new wm9713_hpl_mixer_controls[] = {
295SOC_DAPM_SINGLE("Beep Playback Switch", HPL_MIXER, 5, 1, 0), 325WM9713_HP_MIXER_CTRL("Beep Playback Switch", HPL_MIXER, 5),
296SOC_DAPM_SINGLE("Voice Playback Switch", HPL_MIXER, 4, 1, 0), 326WM9713_HP_MIXER_CTRL("Voice Playback Switch", HPL_MIXER, 4),
297SOC_DAPM_SINGLE("Aux Playback Switch", HPL_MIXER, 3, 1, 0), 327WM9713_HP_MIXER_CTRL("Aux Playback Switch", HPL_MIXER, 3),
298SOC_DAPM_SINGLE("PCM Playback Switch", HPL_MIXER, 2, 1, 0), 328WM9713_HP_MIXER_CTRL("PCM Playback Switch", HPL_MIXER, 2),
299SOC_DAPM_SINGLE("MonoIn Playback Switch", HPL_MIXER, 1, 1, 0), 329WM9713_HP_MIXER_CTRL("MonoIn Playback Switch", HPL_MIXER, 1),
300SOC_DAPM_SINGLE("Bypass Playback Switch", HPL_MIXER, 0, 1, 0), 330WM9713_HP_MIXER_CTRL("Bypass Playback Switch", HPL_MIXER, 0),
301}; 331};
302 332
303/* Right Headphone Mixers */ 333/* Right Headphone Mixers */
304static const struct snd_kcontrol_new wm9713_hpr_mixer_controls[] = { 334static const struct snd_kcontrol_new wm9713_hpr_mixer_controls[] = {
305SOC_DAPM_SINGLE("Beep Playback Switch", HPR_MIXER, 5, 1, 0), 335WM9713_HP_MIXER_CTRL("Beep Playback Switch", HPR_MIXER, 5),
306SOC_DAPM_SINGLE("Voice Playback Switch", HPR_MIXER, 4, 1, 0), 336WM9713_HP_MIXER_CTRL("Voice Playback Switch", HPR_MIXER, 4),
307SOC_DAPM_SINGLE("Aux Playback Switch", HPR_MIXER, 3, 1, 0), 337WM9713_HP_MIXER_CTRL("Aux Playback Switch", HPR_MIXER, 3),
308SOC_DAPM_SINGLE("PCM Playback Switch", HPR_MIXER, 2, 1, 0), 338WM9713_HP_MIXER_CTRL("PCM Playback Switch", HPR_MIXER, 2),
309SOC_DAPM_SINGLE("MonoIn Playback Switch", HPR_MIXER, 1, 1, 0), 339WM9713_HP_MIXER_CTRL("MonoIn Playback Switch", HPR_MIXER, 1),
310SOC_DAPM_SINGLE("Bypass Playback Switch", HPR_MIXER, 0, 1, 0), 340WM9713_HP_MIXER_CTRL("Bypass Playback Switch", HPR_MIXER, 0),
311}; 341};
312 342
313/* headphone capture mux */ 343/* headphone capture mux */
@@ -429,12 +459,10 @@ SND_SOC_DAPM_MUX("Mic A Source", SND_SOC_NOPM, 0, 0,
429 &wm9713_mic_sel_mux_controls), 459 &wm9713_mic_sel_mux_controls),
430SND_SOC_DAPM_MUX("Mic B Source", SND_SOC_NOPM, 0, 0, 460SND_SOC_DAPM_MUX("Mic B Source", SND_SOC_NOPM, 0, 0,
431 &wm9713_micb_sel_mux_controls), 461 &wm9713_micb_sel_mux_controls),
432SND_SOC_DAPM_MIXER_E("Left HP Mixer", AC97_EXTENDED_MID, 3, 1, 462SND_SOC_DAPM_MIXER("Left HP Mixer", AC97_EXTENDED_MID, 3, 1,
433 &wm9713_hpl_mixer_controls[0], ARRAY_SIZE(wm9713_hpl_mixer_controls), 463 &wm9713_hpl_mixer_controls[0], ARRAY_SIZE(wm9713_hpl_mixer_controls)),
434 mixer_event, SND_SOC_DAPM_POST_REG), 464SND_SOC_DAPM_MIXER("Right HP Mixer", AC97_EXTENDED_MID, 2, 1,
435SND_SOC_DAPM_MIXER_E("Right HP Mixer", AC97_EXTENDED_MID, 2, 1, 465 &wm9713_hpr_mixer_controls[0], ARRAY_SIZE(wm9713_hpr_mixer_controls)),
436 &wm9713_hpr_mixer_controls[0], ARRAY_SIZE(wm9713_hpr_mixer_controls),
437 mixer_event, SND_SOC_DAPM_POST_REG),
438SND_SOC_DAPM_MIXER("Mono Mixer", AC97_EXTENDED_MID, 0, 1, 466SND_SOC_DAPM_MIXER("Mono Mixer", AC97_EXTENDED_MID, 0, 1,
439 &wm9713_mono_mixer_controls[0], ARRAY_SIZE(wm9713_mono_mixer_controls)), 467 &wm9713_mono_mixer_controls[0], ARRAY_SIZE(wm9713_mono_mixer_controls)),
440SND_SOC_DAPM_MIXER("Speaker Mixer", AC97_EXTENDED_MID, 1, 1, 468SND_SOC_DAPM_MIXER("Speaker Mixer", AC97_EXTENDED_MID, 1, 1,
@@ -647,12 +675,13 @@ static const struct snd_soc_dapm_route wm9713_audio_map[] = {
647static unsigned int ac97_read(struct snd_soc_codec *codec, 675static unsigned int ac97_read(struct snd_soc_codec *codec,
648 unsigned int reg) 676 unsigned int reg)
649{ 677{
678 struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec);
650 u16 *cache = codec->reg_cache; 679 u16 *cache = codec->reg_cache;
651 680
652 if (reg == AC97_RESET || reg == AC97_GPIO_STATUS || 681 if (reg == AC97_RESET || reg == AC97_GPIO_STATUS ||
653 reg == AC97_VENDOR_ID1 || reg == AC97_VENDOR_ID2 || 682 reg == AC97_VENDOR_ID1 || reg == AC97_VENDOR_ID2 ||
654 reg == AC97_CD) 683 reg == AC97_CD)
655 return soc_ac97_ops->read(codec->ac97, reg); 684 return soc_ac97_ops->read(wm9713->ac97, reg);
656 else { 685 else {
657 reg = reg >> 1; 686 reg = reg >> 1;
658 687
@@ -666,9 +695,10 @@ static unsigned int ac97_read(struct snd_soc_codec *codec,
666static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, 695static int ac97_write(struct snd_soc_codec *codec, unsigned int reg,
667 unsigned int val) 696 unsigned int val)
668{ 697{
698 struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec);
699
669 u16 *cache = codec->reg_cache; 700 u16 *cache = codec->reg_cache;
670 if (reg < 0x7c) 701 soc_ac97_ops->write(wm9713->ac97, reg, val);
671 soc_ac97_ops->write(codec->ac97, reg, val);
672 reg = reg >> 1; 702 reg = reg >> 1;
673 if (reg < (ARRAY_SIZE(wm9713_reg))) 703 if (reg < (ARRAY_SIZE(wm9713_reg)))
674 cache[reg] = val; 704 cache[reg] = val;
@@ -689,7 +719,8 @@ struct _pll_div {
689 * to allow rounding later */ 719 * to allow rounding later */
690#define FIXED_PLL_SIZE ((1 << 22) * 10) 720#define FIXED_PLL_SIZE ((1 << 22) * 10)
691 721
692static void pll_factors(struct _pll_div *pll_div, unsigned int source) 722static void pll_factors(struct snd_soc_codec *codec,
723 struct _pll_div *pll_div, unsigned int source)
693{ 724{
694 u64 Kpart; 725 u64 Kpart;
695 unsigned int K, Ndiv, Nmod, target; 726 unsigned int K, Ndiv, Nmod, target;
@@ -724,7 +755,7 @@ static void pll_factors(struct _pll_div *pll_div, unsigned int source)
724 755
725 Ndiv = target / source; 756 Ndiv = target / source;
726 if ((Ndiv < 5) || (Ndiv > 12)) 757 if ((Ndiv < 5) || (Ndiv > 12))
727 printk(KERN_WARNING 758 dev_warn(codec->dev,
728 "WM9713 PLL N value %u out of recommended range!\n", 759 "WM9713 PLL N value %u out of recommended range!\n",
729 Ndiv); 760 Ndiv);
730 761
@@ -768,7 +799,7 @@ static int wm9713_set_pll(struct snd_soc_codec *codec,
768 return 0; 799 return 0;
769 } 800 }
770 801
771 pll_factors(&pll_div, freq_in); 802 pll_factors(codec, &pll_div, freq_in);
772 803
773 if (pll_div.k == 0) { 804 if (pll_div.k == 0) {
774 reg = (pll_div.n << 12) | (pll_div.lf << 11) | 805 reg = (pll_div.n << 12) | (pll_div.lf << 11) |
@@ -1049,7 +1080,6 @@ static const struct snd_soc_dai_ops wm9713_dai_ops_voice = {
1049static struct snd_soc_dai_driver wm9713_dai[] = { 1080static struct snd_soc_dai_driver wm9713_dai[] = {
1050{ 1081{
1051 .name = "wm9713-hifi", 1082 .name = "wm9713-hifi",
1052 .ac97_control = 1,
1053 .playback = { 1083 .playback = {
1054 .stream_name = "HiFi Playback", 1084 .stream_name = "HiFi Playback",
1055 .channels_min = 1, 1085 .channels_min = 1,
@@ -1095,17 +1125,22 @@ static struct snd_soc_dai_driver wm9713_dai[] = {
1095 1125
1096int wm9713_reset(struct snd_soc_codec *codec, int try_warm) 1126int wm9713_reset(struct snd_soc_codec *codec, int try_warm)
1097{ 1127{
1128 struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec);
1129
1098 if (try_warm && soc_ac97_ops->warm_reset) { 1130 if (try_warm && soc_ac97_ops->warm_reset) {
1099 soc_ac97_ops->warm_reset(codec->ac97); 1131 soc_ac97_ops->warm_reset(wm9713->ac97);
1100 if (ac97_read(codec, 0) == wm9713_reg[0]) 1132 if (ac97_read(codec, 0) == wm9713_reg[0])
1101 return 1; 1133 return 1;
1102 } 1134 }
1103 1135
1104 soc_ac97_ops->reset(codec->ac97); 1136 soc_ac97_ops->reset(wm9713->ac97);
1105 if (soc_ac97_ops->warm_reset) 1137 if (soc_ac97_ops->warm_reset)
1106 soc_ac97_ops->warm_reset(codec->ac97); 1138 soc_ac97_ops->warm_reset(wm9713->ac97);
1107 if (ac97_read(codec, 0) != wm9713_reg[0]) 1139 if (ac97_read(codec, 0) != wm9713_reg[0]) {
1140 dev_err(codec->dev, "Failed to reset: AC97 link error\n");
1108 return -EIO; 1141 return -EIO;
1142 }
1143
1109 return 0; 1144 return 0;
1110} 1145}
1111EXPORT_SYMBOL_GPL(wm9713_reset); 1146EXPORT_SYMBOL_GPL(wm9713_reset);
@@ -1163,10 +1198,8 @@ static int wm9713_soc_resume(struct snd_soc_codec *codec)
1163 u16 *cache = codec->reg_cache; 1198 u16 *cache = codec->reg_cache;
1164 1199
1165 ret = wm9713_reset(codec, 1); 1200 ret = wm9713_reset(codec, 1);
1166 if (ret < 0) { 1201 if (ret < 0)
1167 printk(KERN_ERR "could not reset AC97 codec\n");
1168 return ret; 1202 return ret;
1169 }
1170 1203
1171 wm9713_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 1204 wm9713_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1172 1205
@@ -1180,7 +1213,7 @@ static int wm9713_soc_resume(struct snd_soc_codec *codec)
1180 if (i == AC97_POWERDOWN || i == AC97_EXTENDED_MID || 1213 if (i == AC97_POWERDOWN || i == AC97_EXTENDED_MID ||
1181 i == AC97_EXTENDED_MSTATUS || i > 0x66) 1214 i == AC97_EXTENDED_MSTATUS || i > 0x66)
1182 continue; 1215 continue;
1183 soc_ac97_ops->write(codec->ac97, i, cache[i>>1]); 1216 soc_ac97_ops->write(wm9713->ac97, i, cache[i>>1]);
1184 } 1217 }
1185 } 1218 }
1186 1219
@@ -1189,50 +1222,36 @@ static int wm9713_soc_resume(struct snd_soc_codec *codec)
1189 1222
1190static int wm9713_soc_probe(struct snd_soc_codec *codec) 1223static int wm9713_soc_probe(struct snd_soc_codec *codec)
1191{ 1224{
1192 struct wm9713_priv *wm9713; 1225 struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec);
1193 int ret = 0, reg; 1226 int ret = 0, reg;
1194 1227
1195 wm9713 = kzalloc(sizeof(struct wm9713_priv), GFP_KERNEL); 1228 wm9713->ac97 = snd_soc_new_ac97_codec(codec);
1196 if (wm9713 == NULL) 1229 if (IS_ERR(wm9713->ac97))
1197 return -ENOMEM; 1230 return PTR_ERR(wm9713->ac97);
1198 snd_soc_codec_set_drvdata(codec, wm9713);
1199
1200 ret = snd_soc_new_ac97_codec(codec, soc_ac97_ops, 0);
1201 if (ret < 0)
1202 goto codec_err;
1203 1231
1204 /* do a cold reset for the controller and then try 1232 /* do a cold reset for the controller and then try
1205 * a warm reset followed by an optional cold reset for codec */ 1233 * a warm reset followed by an optional cold reset for codec */
1206 wm9713_reset(codec, 0); 1234 wm9713_reset(codec, 0);
1207 ret = wm9713_reset(codec, 1); 1235 ret = wm9713_reset(codec, 1);
1208 if (ret < 0) { 1236 if (ret < 0)
1209 printk(KERN_ERR "Failed to reset WM9713: AC97 link error\n");
1210 goto reset_err; 1237 goto reset_err;
1211 }
1212
1213 wm9713_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1214 1238
1215 /* unmute the adc - move to kcontrol */ 1239 /* unmute the adc - move to kcontrol */
1216 reg = ac97_read(codec, AC97_CD) & 0x7fff; 1240 reg = ac97_read(codec, AC97_CD) & 0x7fff;
1217 ac97_write(codec, AC97_CD, reg); 1241 ac97_write(codec, AC97_CD, reg);
1218 1242
1219 snd_soc_add_codec_controls(codec, wm9713_snd_ac97_controls,
1220 ARRAY_SIZE(wm9713_snd_ac97_controls));
1221
1222 return 0; 1243 return 0;
1223 1244
1224reset_err: 1245reset_err:
1225 snd_soc_free_ac97_codec(codec); 1246 snd_soc_free_ac97_codec(wm9713->ac97);
1226codec_err:
1227 kfree(wm9713);
1228 return ret; 1247 return ret;
1229} 1248}
1230 1249
1231static int wm9713_soc_remove(struct snd_soc_codec *codec) 1250static int wm9713_soc_remove(struct snd_soc_codec *codec)
1232{ 1251{
1233 struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec); 1252 struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec);
1234 snd_soc_free_ac97_codec(codec); 1253
1235 kfree(wm9713); 1254 snd_soc_free_ac97_codec(wm9713->ac97);
1236 return 0; 1255 return 0;
1237} 1256}
1238 1257
@@ -1248,6 +1267,9 @@ static struct snd_soc_codec_driver soc_codec_dev_wm9713 = {
1248 .reg_word_size = sizeof(u16), 1267 .reg_word_size = sizeof(u16),
1249 .reg_cache_step = 2, 1268 .reg_cache_step = 2,
1250 .reg_cache_default = wm9713_reg, 1269 .reg_cache_default = wm9713_reg,
1270
1271 .controls = wm9713_snd_ac97_controls,
1272 .num_controls = ARRAY_SIZE(wm9713_snd_ac97_controls),
1251 .dapm_widgets = wm9713_dapm_widgets, 1273 .dapm_widgets = wm9713_dapm_widgets,
1252 .num_dapm_widgets = ARRAY_SIZE(wm9713_dapm_widgets), 1274 .num_dapm_widgets = ARRAY_SIZE(wm9713_dapm_widgets),
1253 .dapm_routes = wm9713_audio_map, 1275 .dapm_routes = wm9713_audio_map,
@@ -1256,6 +1278,16 @@ static struct snd_soc_codec_driver soc_codec_dev_wm9713 = {
1256 1278
1257static int wm9713_probe(struct platform_device *pdev) 1279static int wm9713_probe(struct platform_device *pdev)
1258{ 1280{
1281 struct wm9713_priv *wm9713;
1282
1283 wm9713 = devm_kzalloc(&pdev->dev, sizeof(*wm9713), GFP_KERNEL);
1284 if (wm9713 == NULL)
1285 return -ENOMEM;
1286
1287 mutex_init(&wm9713->lock);
1288
1289 platform_set_drvdata(pdev, wm9713);
1290
1259 return snd_soc_register_codec(&pdev->dev, 1291 return snd_soc_register_codec(&pdev->dev,
1260 &soc_codec_dev_wm9713, wm9713_dai, ARRAY_SIZE(wm9713_dai)); 1292 &soc_codec_dev_wm9713, wm9713_dai, ARRAY_SIZE(wm9713_dai));
1261} 1293}