aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/wm8990.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/codecs/wm8990.c')
-rw-r--r--sound/soc/codecs/wm8990.c43
1 files changed, 34 insertions, 9 deletions
diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c
index 572d22b0880b..5b5afc144478 100644
--- a/sound/soc/codecs/wm8990.c
+++ b/sound/soc/codecs/wm8990.c
@@ -106,6 +106,7 @@ static const u16 wm8990_reg[] = {
106 0x0008, /* R60 - PLL1 */ 106 0x0008, /* R60 - PLL1 */
107 0x0031, /* R61 - PLL2 */ 107 0x0031, /* R61 - PLL2 */
108 0x0026, /* R62 - PLL3 */ 108 0x0026, /* R62 - PLL3 */
109 0x0000, /* R63 - Driver internal */
109}; 110};
110 111
111/* 112/*
@@ -126,10 +127,9 @@ static inline void wm8990_write_reg_cache(struct snd_soc_codec *codec,
126 unsigned int reg, unsigned int value) 127 unsigned int reg, unsigned int value)
127{ 128{
128 u16 *cache = codec->reg_cache; 129 u16 *cache = codec->reg_cache;
129 BUG_ON(reg > (ARRAY_SIZE(wm8990_reg)) - 1);
130 130
131 /* Reset register is uncached */ 131 /* Reset register and reserved registers are uncached */
132 if (reg == 0) 132 if (reg == 0 || reg > ARRAY_SIZE(wm8990_reg) - 1)
133 return; 133 return;
134 134
135 cache[reg] = value; 135 cache[reg] = value;
@@ -1172,7 +1172,8 @@ static int wm8990_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
1172 * Set PCM DAI bit size and sample rate. 1172 * Set PCM DAI bit size and sample rate.
1173 */ 1173 */
1174static int wm8990_hw_params(struct snd_pcm_substream *substream, 1174static int wm8990_hw_params(struct snd_pcm_substream *substream,
1175 struct snd_pcm_hw_params *params) 1175 struct snd_pcm_hw_params *params,
1176 struct snd_soc_dai *dai)
1176{ 1177{
1177 struct snd_soc_pcm_runtime *rtd = substream->private_data; 1178 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1178 struct snd_soc_device *socdev = rtd->socdev; 1179 struct snd_soc_device *socdev = rtd->socdev;
@@ -1222,8 +1223,14 @@ static int wm8990_set_bias_level(struct snd_soc_codec *codec,
1222 switch (level) { 1223 switch (level) {
1223 case SND_SOC_BIAS_ON: 1224 case SND_SOC_BIAS_ON:
1224 break; 1225 break;
1226
1225 case SND_SOC_BIAS_PREPARE: 1227 case SND_SOC_BIAS_PREPARE:
1228 /* VMID=2*50k */
1229 val = wm8990_read_reg_cache(codec, WM8990_POWER_MANAGEMENT_1) &
1230 ~WM8990_VMID_MODE_MASK;
1231 wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, val | 0x2);
1226 break; 1232 break;
1233
1227 case SND_SOC_BIAS_STANDBY: 1234 case SND_SOC_BIAS_STANDBY:
1228 if (codec->bias_level == SND_SOC_BIAS_OFF) { 1235 if (codec->bias_level == SND_SOC_BIAS_OFF) {
1229 /* Enable all output discharge bits */ 1236 /* Enable all output discharge bits */
@@ -1272,10 +1279,17 @@ static int wm8990_set_bias_level(struct snd_soc_codec *codec,
1272 1279
1273 /* disable POBCTRL, SOFT_ST and BUFDCOPEN */ 1280 /* disable POBCTRL, SOFT_ST and BUFDCOPEN */
1274 wm8990_write(codec, WM8990_ANTIPOP2, WM8990_BUFIOEN); 1281 wm8990_write(codec, WM8990_ANTIPOP2, WM8990_BUFIOEN);
1275 } else {
1276 /* ON -> standby */
1277 1282
1283 /* Enable workaround for ADC clocking issue. */
1284 wm8990_write(codec, WM8990_EXT_ACCESS_ENA, 0x2);
1285 wm8990_write(codec, WM8990_EXT_CTL1, 0xa003);
1286 wm8990_write(codec, WM8990_EXT_ACCESS_ENA, 0);
1278 } 1287 }
1288
1289 /* VMID=2*250k */
1290 val = wm8990_read_reg_cache(codec, WM8990_POWER_MANAGEMENT_1) &
1291 ~WM8990_VMID_MODE_MASK;
1292 wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, val | 0x4);
1279 break; 1293 break;
1280 1294
1281 case SND_SOC_BIAS_OFF: 1295 case SND_SOC_BIAS_OFF:
@@ -1349,8 +1363,7 @@ struct snd_soc_dai wm8990_dai = {
1349 .rates = WM8990_RATES, 1363 .rates = WM8990_RATES,
1350 .formats = WM8990_FORMATS,}, 1364 .formats = WM8990_FORMATS,},
1351 .ops = { 1365 .ops = {
1352 .hw_params = wm8990_hw_params,}, 1366 .hw_params = wm8990_hw_params,
1353 .dai_ops = {
1354 .digital_mute = wm8990_mute, 1367 .digital_mute = wm8990_mute,
1355 .set_fmt = wm8990_set_dai_fmt, 1368 .set_fmt = wm8990_set_dai_fmt,
1356 .set_clkdiv = wm8990_set_dai_clkdiv, 1369 .set_clkdiv = wm8990_set_dai_clkdiv,
@@ -1449,7 +1462,7 @@ static int wm8990_init(struct snd_soc_device *socdev)
1449 1462
1450 wm8990_add_controls(codec); 1463 wm8990_add_controls(codec);
1451 wm8990_add_widgets(codec); 1464 wm8990_add_widgets(codec);
1452 ret = snd_soc_register_card(socdev); 1465 ret = snd_soc_init_card(socdev);
1453 if (ret < 0) { 1466 if (ret < 0) {
1454 printk(KERN_ERR "wm8990: failed to register card\n"); 1467 printk(KERN_ERR "wm8990: failed to register card\n");
1455 goto card_err; 1468 goto card_err;
@@ -1630,6 +1643,18 @@ struct snd_soc_codec_device soc_codec_dev_wm8990 = {
1630}; 1643};
1631EXPORT_SYMBOL_GPL(soc_codec_dev_wm8990); 1644EXPORT_SYMBOL_GPL(soc_codec_dev_wm8990);
1632 1645
1646static int __init wm8990_modinit(void)
1647{
1648 return snd_soc_register_dai(&wm8990_dai);
1649}
1650module_init(wm8990_modinit);
1651
1652static void __exit wm8990_exit(void)
1653{
1654 snd_soc_unregister_dai(&wm8990_dai);
1655}
1656module_exit(wm8990_exit);
1657
1633MODULE_DESCRIPTION("ASoC WM8990 driver"); 1658MODULE_DESCRIPTION("ASoC WM8990 driver");
1634MODULE_AUTHOR("Liam Girdwood"); 1659MODULE_AUTHOR("Liam Girdwood");
1635MODULE_LICENSE("GPL"); 1660MODULE_LICENSE("GPL");