diff options
Diffstat (limited to 'sound/soc/codecs/wm9081.c')
-rw-r--r-- | sound/soc/codecs/wm9081.c | 99 |
1 files changed, 49 insertions, 50 deletions
diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c index ecc7c37180c7..91c6b39de50c 100644 --- a/sound/soc/codecs/wm9081.c +++ b/sound/soc/codecs/wm9081.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/moduleparam.h> | 15 | #include <linux/moduleparam.h> |
16 | #include <linux/init.h> | 16 | #include <linux/init.h> |
17 | #include <linux/delay.h> | 17 | #include <linux/delay.h> |
18 | #include <linux/device.h> | ||
18 | #include <linux/pm.h> | 19 | #include <linux/pm.h> |
19 | #include <linux/i2c.h> | 20 | #include <linux/i2c.h> |
20 | #include <linux/platform_device.h> | 21 | #include <linux/platform_device.h> |
@@ -23,7 +24,6 @@ | |||
23 | #include <sound/pcm.h> | 24 | #include <sound/pcm.h> |
24 | #include <sound/pcm_params.h> | 25 | #include <sound/pcm_params.h> |
25 | #include <sound/soc.h> | 26 | #include <sound/soc.h> |
26 | #include <sound/soc-dapm.h> | ||
27 | #include <sound/initval.h> | 27 | #include <sound/initval.h> |
28 | #include <sound/tlv.h> | 28 | #include <sound/tlv.h> |
29 | 29 | ||
@@ -158,7 +158,6 @@ static struct { | |||
158 | struct wm9081_priv { | 158 | struct wm9081_priv { |
159 | enum snd_soc_control_type control_type; | 159 | enum snd_soc_control_type control_type; |
160 | void *control_data; | 160 | void *control_data; |
161 | u16 reg_cache[WM9081_MAX_REGISTER + 1]; | ||
162 | int sysclk_source; | 161 | int sysclk_source; |
163 | int mclk_rate; | 162 | int mclk_rate; |
164 | int sysclk_rate; | 163 | int sysclk_rate; |
@@ -168,10 +167,10 @@ struct wm9081_priv { | |||
168 | int fll_fref; | 167 | int fll_fref; |
169 | int fll_fout; | 168 | int fll_fout; |
170 | int tdm_width; | 169 | int tdm_width; |
171 | struct wm9081_retune_mobile_config *retune; | 170 | struct wm9081_pdata pdata; |
172 | }; | 171 | }; |
173 | 172 | ||
174 | static int wm9081_volatile_register(unsigned int reg) | 173 | static int wm9081_volatile_register(struct snd_soc_codec *codec, unsigned int reg) |
175 | { | 174 | { |
176 | switch (reg) { | 175 | switch (reg) { |
177 | case WM9081_SOFTWARE_RESET: | 176 | case WM9081_SOFTWARE_RESET: |
@@ -306,7 +305,7 @@ static int speaker_mode_get(struct snd_kcontrol *kcontrol, | |||
306 | /* | 305 | /* |
307 | * Stop any attempts to change speaker mode while the speaker is enabled. | 306 | * Stop any attempts to change speaker mode while the speaker is enabled. |
308 | * | 307 | * |
309 | * We also have some special anti-pop controls dependant on speaker | 308 | * We also have some special anti-pop controls dependent on speaker |
310 | * mode which must be changed along with the mode. | 309 | * mode which must be changed along with the mode. |
311 | */ | 310 | */ |
312 | static int speaker_mode_put(struct snd_kcontrol *kcontrol, | 311 | static int speaker_mode_put(struct snd_kcontrol *kcontrol, |
@@ -390,27 +389,6 @@ SOC_DAPM_SINGLE("IN2 Switch", WM9081_ANALOGUE_MIXER, 2, 1, 0), | |||
390 | SOC_DAPM_SINGLE("Playback Switch", WM9081_ANALOGUE_MIXER, 4, 1, 0), | 389 | SOC_DAPM_SINGLE("Playback Switch", WM9081_ANALOGUE_MIXER, 4, 1, 0), |
391 | }; | 390 | }; |
392 | 391 | ||
393 | static int speaker_event(struct snd_soc_dapm_widget *w, | ||
394 | struct snd_kcontrol *kcontrol, int event) | ||
395 | { | ||
396 | struct snd_soc_codec *codec = w->codec; | ||
397 | unsigned int reg = snd_soc_read(codec, WM9081_POWER_MANAGEMENT); | ||
398 | |||
399 | switch (event) { | ||
400 | case SND_SOC_DAPM_POST_PMU: | ||
401 | reg |= WM9081_SPK_ENA; | ||
402 | break; | ||
403 | |||
404 | case SND_SOC_DAPM_PRE_PMD: | ||
405 | reg &= ~WM9081_SPK_ENA; | ||
406 | break; | ||
407 | } | ||
408 | |||
409 | snd_soc_write(codec, WM9081_POWER_MANAGEMENT, reg); | ||
410 | |||
411 | return 0; | ||
412 | } | ||
413 | |||
414 | struct _fll_div { | 392 | struct _fll_div { |
415 | u16 fll_fratio; | 393 | u16 fll_fratio; |
416 | u16 fll_outdiv; | 394 | u16 fll_outdiv; |
@@ -478,7 +456,7 @@ static int fll_factors(struct _fll_div *fll_div, unsigned int Fref, | |||
478 | 456 | ||
479 | pr_debug("Fvco=%dHz\n", target); | 457 | pr_debug("Fvco=%dHz\n", target); |
480 | 458 | ||
481 | /* Find an appropraite FLL_FRATIO and factor it out of the target */ | 459 | /* Find an appropriate FLL_FRATIO and factor it out of the target */ |
482 | for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) { | 460 | for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) { |
483 | if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) { | 461 | if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) { |
484 | fll_div->fll_fratio = fll_fratios[i].fll_fratio; | 462 | fll_div->fll_fratio = fll_fratios[i].fll_fratio; |
@@ -591,6 +569,10 @@ static int wm9081_set_fll(struct snd_soc_codec *codec, int fll_id, | |||
591 | reg5 |= fll_div.fll_clk_ref_div << WM9081_FLL_CLK_REF_DIV_SHIFT; | 569 | reg5 |= fll_div.fll_clk_ref_div << WM9081_FLL_CLK_REF_DIV_SHIFT; |
592 | snd_soc_write(codec, WM9081_FLL_CONTROL_5, reg5); | 570 | snd_soc_write(codec, WM9081_FLL_CONTROL_5, reg5); |
593 | 571 | ||
572 | /* Set gain to the recommended value */ | ||
573 | snd_soc_update_bits(codec, WM9081_FLL_CONTROL_4, | ||
574 | WM9081_FLL_GAIN_MASK, 0); | ||
575 | |||
594 | /* Enable the FLL */ | 576 | /* Enable the FLL */ |
595 | snd_soc_write(codec, WM9081_FLL_CONTROL_1, reg1 | WM9081_FLL_ENA); | 577 | snd_soc_write(codec, WM9081_FLL_CONTROL_1, reg1 | WM9081_FLL_ENA); |
596 | 578 | ||
@@ -744,9 +726,8 @@ SND_SOC_DAPM_MIXER_NAMED_CTL("Mixer", SND_SOC_NOPM, 0, 0, | |||
744 | 726 | ||
745 | SND_SOC_DAPM_PGA("LINEOUT PGA", WM9081_POWER_MANAGEMENT, 4, 0, NULL, 0), | 727 | SND_SOC_DAPM_PGA("LINEOUT PGA", WM9081_POWER_MANAGEMENT, 4, 0, NULL, 0), |
746 | 728 | ||
747 | SND_SOC_DAPM_PGA_E("Speaker PGA", WM9081_POWER_MANAGEMENT, 2, 0, NULL, 0, | 729 | SND_SOC_DAPM_PGA("Speaker PGA", WM9081_POWER_MANAGEMENT, 2, 0, NULL, 0), |
748 | speaker_event, | 730 | SND_SOC_DAPM_PGA("Speaker", WM9081_POWER_MANAGEMENT, 1, 0, NULL, 0), |
749 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), | ||
750 | 731 | ||
751 | SND_SOC_DAPM_OUTPUT("LINEOUT"), | 732 | SND_SOC_DAPM_OUTPUT("LINEOUT"), |
752 | SND_SOC_DAPM_OUTPUT("SPKN"), | 733 | SND_SOC_DAPM_OUTPUT("SPKN"), |
@@ -759,7 +740,7 @@ SND_SOC_DAPM_SUPPLY("TOCLK", WM9081_CLOCK_CONTROL_3, 2, 0, NULL, 0), | |||
759 | }; | 740 | }; |
760 | 741 | ||
761 | 742 | ||
762 | static const struct snd_soc_dapm_route audio_paths[] = { | 743 | static const struct snd_soc_dapm_route wm9081_audio_paths[] = { |
763 | { "DAC", NULL, "CLK_SYS" }, | 744 | { "DAC", NULL, "CLK_SYS" }, |
764 | { "DAC", NULL, "CLK_DSP" }, | 745 | { "DAC", NULL, "CLK_DSP" }, |
765 | 746 | ||
@@ -777,8 +758,10 @@ static const struct snd_soc_dapm_route audio_paths[] = { | |||
777 | { "Speaker PGA", NULL, "TOCLK" }, | 758 | { "Speaker PGA", NULL, "TOCLK" }, |
778 | { "Speaker PGA", NULL, "CLK_SYS" }, | 759 | { "Speaker PGA", NULL, "CLK_SYS" }, |
779 | 760 | ||
780 | { "SPKN", NULL, "Speaker PGA" }, | 761 | { "Speaker", NULL, "Speaker PGA" }, |
781 | { "SPKP", NULL, "Speaker PGA" }, | 762 | |
763 | { "SPKN", NULL, "Speaker" }, | ||
764 | { "SPKP", NULL, "Speaker" }, | ||
782 | }; | 765 | }; |
783 | 766 | ||
784 | static int wm9081_set_bias_level(struct snd_soc_codec *codec, | 767 | static int wm9081_set_bias_level(struct snd_soc_codec *codec, |
@@ -805,7 +788,7 @@ static int wm9081_set_bias_level(struct snd_soc_codec *codec, | |||
805 | 788 | ||
806 | case SND_SOC_BIAS_STANDBY: | 789 | case SND_SOC_BIAS_STANDBY: |
807 | /* Initial cold start */ | 790 | /* Initial cold start */ |
808 | if (codec->bias_level == SND_SOC_BIAS_OFF) { | 791 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { |
809 | /* Disable LINEOUT discharge */ | 792 | /* Disable LINEOUT discharge */ |
810 | reg = snd_soc_read(codec, WM9081_ANTI_POP_CONTROL); | 793 | reg = snd_soc_read(codec, WM9081_ANTI_POP_CONTROL); |
811 | reg &= ~WM9081_LINEOUT_DISCH; | 794 | reg &= ~WM9081_LINEOUT_DISCH; |
@@ -865,7 +848,7 @@ static int wm9081_set_bias_level(struct snd_soc_codec *codec, | |||
865 | break; | 848 | break; |
866 | } | 849 | } |
867 | 850 | ||
868 | codec->bias_level = level; | 851 | codec->dapm.bias_level = level; |
869 | 852 | ||
870 | return 0; | 853 | return 0; |
871 | } | 854 | } |
@@ -1079,21 +1062,22 @@ static int wm9081_hw_params(struct snd_pcm_substream *substream, | |||
1079 | aif4 |= wm9081->bclk / wm9081->fs; | 1062 | aif4 |= wm9081->bclk / wm9081->fs; |
1080 | 1063 | ||
1081 | /* Apply a ReTune Mobile configuration if it's in use */ | 1064 | /* Apply a ReTune Mobile configuration if it's in use */ |
1082 | if (wm9081->retune) { | 1065 | if (wm9081->pdata.num_retune_configs) { |
1083 | struct wm9081_retune_mobile_config *retune = wm9081->retune; | 1066 | struct wm9081_pdata *pdata = &wm9081->pdata; |
1084 | struct wm9081_retune_mobile_setting *s; | 1067 | struct wm9081_retune_mobile_setting *s; |
1085 | int eq1; | 1068 | int eq1; |
1086 | 1069 | ||
1087 | best = 0; | 1070 | best = 0; |
1088 | best_val = abs(retune->configs[0].rate - wm9081->fs); | 1071 | best_val = abs(pdata->retune_configs[0].rate - wm9081->fs); |
1089 | for (i = 0; i < retune->num_configs; i++) { | 1072 | for (i = 0; i < pdata->num_retune_configs; i++) { |
1090 | cur_val = abs(retune->configs[i].rate - wm9081->fs); | 1073 | cur_val = abs(pdata->retune_configs[i].rate - |
1074 | wm9081->fs); | ||
1091 | if (cur_val < best_val) { | 1075 | if (cur_val < best_val) { |
1092 | best_val = cur_val; | 1076 | best_val = cur_val; |
1093 | best = i; | 1077 | best = i; |
1094 | } | 1078 | } |
1095 | } | 1079 | } |
1096 | s = &retune->configs[best]; | 1080 | s = &pdata->retune_configs[best]; |
1097 | 1081 | ||
1098 | dev_dbg(codec->dev, "ReTune Mobile %s tuned for %dHz\n", | 1082 | dev_dbg(codec->dev, "ReTune Mobile %s tuned for %dHz\n", |
1099 | s->name, s->rate); | 1083 | s->name, s->rate); |
@@ -1136,10 +1120,9 @@ static int wm9081_digital_mute(struct snd_soc_dai *codec_dai, int mute) | |||
1136 | return 0; | 1120 | return 0; |
1137 | } | 1121 | } |
1138 | 1122 | ||
1139 | static int wm9081_set_sysclk(struct snd_soc_dai *codec_dai, | 1123 | static int wm9081_set_sysclk(struct snd_soc_codec *codec, |
1140 | int clk_id, unsigned int freq, int dir) | 1124 | int clk_id, unsigned int freq, int dir) |
1141 | { | 1125 | { |
1142 | struct snd_soc_codec *codec = codec_dai->codec; | ||
1143 | struct wm9081_priv *wm9081 = snd_soc_codec_get_drvdata(codec); | 1126 | struct wm9081_priv *wm9081 = snd_soc_codec_get_drvdata(codec); |
1144 | 1127 | ||
1145 | switch (clk_id) { | 1128 | switch (clk_id) { |
@@ -1204,7 +1187,6 @@ static int wm9081_set_tdm_slot(struct snd_soc_dai *dai, | |||
1204 | 1187 | ||
1205 | static struct snd_soc_dai_ops wm9081_dai_ops = { | 1188 | static struct snd_soc_dai_ops wm9081_dai_ops = { |
1206 | .hw_params = wm9081_hw_params, | 1189 | .hw_params = wm9081_hw_params, |
1207 | .set_sysclk = wm9081_set_sysclk, | ||
1208 | .set_fmt = wm9081_set_dai_fmt, | 1190 | .set_fmt = wm9081_set_dai_fmt, |
1209 | .digital_mute = wm9081_digital_mute, | 1191 | .digital_mute = wm9081_digital_mute, |
1210 | .set_tdm_slot = wm9081_set_tdm_slot, | 1192 | .set_tdm_slot = wm9081_set_tdm_slot, |
@@ -1251,6 +1233,14 @@ static int wm9081_probe(struct snd_soc_codec *codec) | |||
1251 | return ret; | 1233 | return ret; |
1252 | } | 1234 | } |
1253 | 1235 | ||
1236 | reg = 0; | ||
1237 | if (wm9081->pdata.irq_high) | ||
1238 | reg |= WM9081_IRQ_POL; | ||
1239 | if (!wm9081->pdata.irq_cmos) | ||
1240 | reg |= WM9081_IRQ_OP_CTRL; | ||
1241 | snd_soc_update_bits(codec, WM9081_INTERRUPT_CONTROL, | ||
1242 | WM9081_IRQ_POL | WM9081_IRQ_OP_CTRL, reg); | ||
1243 | |||
1254 | wm9081_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 1244 | wm9081_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
1255 | 1245 | ||
1256 | /* Enable zero cross by default */ | 1246 | /* Enable zero cross by default */ |
@@ -1262,17 +1252,13 @@ static int wm9081_probe(struct snd_soc_codec *codec) | |||
1262 | 1252 | ||
1263 | snd_soc_add_controls(codec, wm9081_snd_controls, | 1253 | snd_soc_add_controls(codec, wm9081_snd_controls, |
1264 | ARRAY_SIZE(wm9081_snd_controls)); | 1254 | ARRAY_SIZE(wm9081_snd_controls)); |
1265 | if (!wm9081->retune) { | 1255 | if (!wm9081->pdata.num_retune_configs) { |
1266 | dev_dbg(codec->dev, | 1256 | dev_dbg(codec->dev, |
1267 | "No ReTune Mobile data, using normal EQ\n"); | 1257 | "No ReTune Mobile data, using normal EQ\n"); |
1268 | snd_soc_add_controls(codec, wm9081_eq_controls, | 1258 | snd_soc_add_controls(codec, wm9081_eq_controls, |
1269 | ARRAY_SIZE(wm9081_eq_controls)); | 1259 | ARRAY_SIZE(wm9081_eq_controls)); |
1270 | } | 1260 | } |
1271 | 1261 | ||
1272 | snd_soc_dapm_new_controls(codec, wm9081_dapm_widgets, | ||
1273 | ARRAY_SIZE(wm9081_dapm_widgets)); | ||
1274 | snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths)); | ||
1275 | |||
1276 | return ret; | 1262 | return ret; |
1277 | } | 1263 | } |
1278 | 1264 | ||
@@ -1316,11 +1302,19 @@ static struct snd_soc_codec_driver soc_codec_dev_wm9081 = { | |||
1316 | .remove = wm9081_remove, | 1302 | .remove = wm9081_remove, |
1317 | .suspend = wm9081_suspend, | 1303 | .suspend = wm9081_suspend, |
1318 | .resume = wm9081_resume, | 1304 | .resume = wm9081_resume, |
1305 | |||
1306 | .set_sysclk = wm9081_set_sysclk, | ||
1319 | .set_bias_level = wm9081_set_bias_level, | 1307 | .set_bias_level = wm9081_set_bias_level, |
1308 | |||
1320 | .reg_cache_size = ARRAY_SIZE(wm9081_reg_defaults), | 1309 | .reg_cache_size = ARRAY_SIZE(wm9081_reg_defaults), |
1321 | .reg_word_size = sizeof(u16), | 1310 | .reg_word_size = sizeof(u16), |
1322 | .reg_cache_default = wm9081_reg_defaults, | 1311 | .reg_cache_default = wm9081_reg_defaults, |
1323 | .volatile_register = wm9081_volatile_register, | 1312 | .volatile_register = wm9081_volatile_register, |
1313 | |||
1314 | .dapm_widgets = wm9081_dapm_widgets, | ||
1315 | .num_dapm_widgets = ARRAY_SIZE(wm9081_dapm_widgets), | ||
1316 | .dapm_routes = wm9081_audio_paths, | ||
1317 | .num_dapm_routes = ARRAY_SIZE(wm9081_audio_paths), | ||
1324 | }; | 1318 | }; |
1325 | 1319 | ||
1326 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 1320 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
@@ -1335,8 +1329,13 @@ static __devinit int wm9081_i2c_probe(struct i2c_client *i2c, | |||
1335 | return -ENOMEM; | 1329 | return -ENOMEM; |
1336 | 1330 | ||
1337 | i2c_set_clientdata(i2c, wm9081); | 1331 | i2c_set_clientdata(i2c, wm9081); |
1332 | wm9081->control_type = SND_SOC_I2C; | ||
1338 | wm9081->control_data = i2c; | 1333 | wm9081->control_data = i2c; |
1339 | 1334 | ||
1335 | if (dev_get_platdata(&i2c->dev)) | ||
1336 | memcpy(&wm9081->pdata, dev_get_platdata(&i2c->dev), | ||
1337 | sizeof(wm9081->pdata)); | ||
1338 | |||
1340 | ret = snd_soc_register_codec(&i2c->dev, | 1339 | ret = snd_soc_register_codec(&i2c->dev, |
1341 | &soc_codec_dev_wm9081, &wm9081_dai, 1); | 1340 | &soc_codec_dev_wm9081, &wm9081_dai, 1); |
1342 | if (ret < 0) | 1341 | if (ret < 0) |
@@ -1359,7 +1358,7 @@ MODULE_DEVICE_TABLE(i2c, wm9081_i2c_id); | |||
1359 | 1358 | ||
1360 | static struct i2c_driver wm9081_i2c_driver = { | 1359 | static struct i2c_driver wm9081_i2c_driver = { |
1361 | .driver = { | 1360 | .driver = { |
1362 | .name = "wm9081-codec", | 1361 | .name = "wm9081", |
1363 | .owner = THIS_MODULE, | 1362 | .owner = THIS_MODULE, |
1364 | }, | 1363 | }, |
1365 | .probe = wm9081_i2c_probe, | 1364 | .probe = wm9081_i2c_probe, |