diff options
Diffstat (limited to 'sound/soc/codecs/wm9081.c')
-rw-r--r-- | sound/soc/codecs/wm9081.c | 84 |
1 files changed, 37 insertions, 47 deletions
diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c index cce704c275c6..55cdf2982020 100644 --- a/sound/soc/codecs/wm9081.c +++ b/sound/soc/codecs/wm9081.c | |||
@@ -167,10 +167,10 @@ struct wm9081_priv { | |||
167 | int fll_fref; | 167 | int fll_fref; |
168 | int fll_fout; | 168 | int fll_fout; |
169 | int tdm_width; | 169 | int tdm_width; |
170 | struct wm9081_retune_mobile_config *retune; | 170 | struct wm9081_pdata pdata; |
171 | }; | 171 | }; |
172 | 172 | ||
173 | static int wm9081_volatile_register(unsigned int reg) | 173 | static int wm9081_volatile_register(struct snd_soc_codec *codec, unsigned int reg) |
174 | { | 174 | { |
175 | switch (reg) { | 175 | switch (reg) { |
176 | case WM9081_SOFTWARE_RESET: | 176 | case WM9081_SOFTWARE_RESET: |
@@ -389,27 +389,6 @@ SOC_DAPM_SINGLE("IN2 Switch", WM9081_ANALOGUE_MIXER, 2, 1, 0), | |||
389 | SOC_DAPM_SINGLE("Playback Switch", WM9081_ANALOGUE_MIXER, 4, 1, 0), | 389 | SOC_DAPM_SINGLE("Playback Switch", WM9081_ANALOGUE_MIXER, 4, 1, 0), |
390 | }; | 390 | }; |
391 | 391 | ||
392 | static int speaker_event(struct snd_soc_dapm_widget *w, | ||
393 | struct snd_kcontrol *kcontrol, int event) | ||
394 | { | ||
395 | struct snd_soc_codec *codec = w->codec; | ||
396 | unsigned int reg = snd_soc_read(codec, WM9081_POWER_MANAGEMENT); | ||
397 | |||
398 | switch (event) { | ||
399 | case SND_SOC_DAPM_POST_PMU: | ||
400 | reg |= WM9081_SPK_ENA; | ||
401 | break; | ||
402 | |||
403 | case SND_SOC_DAPM_PRE_PMD: | ||
404 | reg &= ~WM9081_SPK_ENA; | ||
405 | break; | ||
406 | } | ||
407 | |||
408 | snd_soc_write(codec, WM9081_POWER_MANAGEMENT, reg); | ||
409 | |||
410 | return 0; | ||
411 | } | ||
412 | |||
413 | struct _fll_div { | 392 | struct _fll_div { |
414 | u16 fll_fratio; | 393 | u16 fll_fratio; |
415 | u16 fll_outdiv; | 394 | u16 fll_outdiv; |
@@ -747,9 +726,8 @@ SND_SOC_DAPM_MIXER_NAMED_CTL("Mixer", SND_SOC_NOPM, 0, 0, | |||
747 | 726 | ||
748 | 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), |
749 | 728 | ||
750 | 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), |
751 | speaker_event, | 730 | SND_SOC_DAPM_PGA("Speaker", WM9081_POWER_MANAGEMENT, 1, 0, NULL, 0), |
752 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), | ||
753 | 731 | ||
754 | SND_SOC_DAPM_OUTPUT("LINEOUT"), | 732 | SND_SOC_DAPM_OUTPUT("LINEOUT"), |
755 | SND_SOC_DAPM_OUTPUT("SPKN"), | 733 | SND_SOC_DAPM_OUTPUT("SPKN"), |
@@ -762,7 +740,7 @@ SND_SOC_DAPM_SUPPLY("TOCLK", WM9081_CLOCK_CONTROL_3, 2, 0, NULL, 0), | |||
762 | }; | 740 | }; |
763 | 741 | ||
764 | 742 | ||
765 | static const struct snd_soc_dapm_route audio_paths[] = { | 743 | static const struct snd_soc_dapm_route wm9081_audio_paths[] = { |
766 | { "DAC", NULL, "CLK_SYS" }, | 744 | { "DAC", NULL, "CLK_SYS" }, |
767 | { "DAC", NULL, "CLK_DSP" }, | 745 | { "DAC", NULL, "CLK_DSP" }, |
768 | 746 | ||
@@ -780,8 +758,10 @@ static const struct snd_soc_dapm_route audio_paths[] = { | |||
780 | { "Speaker PGA", NULL, "TOCLK" }, | 758 | { "Speaker PGA", NULL, "TOCLK" }, |
781 | { "Speaker PGA", NULL, "CLK_SYS" }, | 759 | { "Speaker PGA", NULL, "CLK_SYS" }, |
782 | 760 | ||
783 | { "SPKN", NULL, "Speaker PGA" }, | 761 | { "Speaker", NULL, "Speaker PGA" }, |
784 | { "SPKP", NULL, "Speaker PGA" }, | 762 | |
763 | { "SPKN", NULL, "Speaker" }, | ||
764 | { "SPKP", NULL, "Speaker" }, | ||
785 | }; | 765 | }; |
786 | 766 | ||
787 | static int wm9081_set_bias_level(struct snd_soc_codec *codec, | 767 | static int wm9081_set_bias_level(struct snd_soc_codec *codec, |
@@ -1082,21 +1062,22 @@ static int wm9081_hw_params(struct snd_pcm_substream *substream, | |||
1082 | aif4 |= wm9081->bclk / wm9081->fs; | 1062 | aif4 |= wm9081->bclk / wm9081->fs; |
1083 | 1063 | ||
1084 | /* Apply a ReTune Mobile configuration if it's in use */ | 1064 | /* Apply a ReTune Mobile configuration if it's in use */ |
1085 | if (wm9081->retune) { | 1065 | if (wm9081->pdata.num_retune_configs) { |
1086 | struct wm9081_retune_mobile_config *retune = wm9081->retune; | 1066 | struct wm9081_pdata *pdata = &wm9081->pdata; |
1087 | struct wm9081_retune_mobile_setting *s; | 1067 | struct wm9081_retune_mobile_setting *s; |
1088 | int eq1; | 1068 | int eq1; |
1089 | 1069 | ||
1090 | best = 0; | 1070 | best = 0; |
1091 | best_val = abs(retune->configs[0].rate - wm9081->fs); | 1071 | best_val = abs(pdata->retune_configs[0].rate - wm9081->fs); |
1092 | for (i = 0; i < retune->num_configs; i++) { | 1072 | for (i = 0; i < pdata->num_retune_configs; i++) { |
1093 | cur_val = abs(retune->configs[i].rate - wm9081->fs); | 1073 | cur_val = abs(pdata->retune_configs[i].rate - |
1074 | wm9081->fs); | ||
1094 | if (cur_val < best_val) { | 1075 | if (cur_val < best_val) { |
1095 | best_val = cur_val; | 1076 | best_val = cur_val; |
1096 | best = i; | 1077 | best = i; |
1097 | } | 1078 | } |
1098 | } | 1079 | } |
1099 | s = &retune->configs[best]; | 1080 | s = &pdata->retune_configs[best]; |
1100 | 1081 | ||
1101 | dev_dbg(codec->dev, "ReTune Mobile %s tuned for %dHz\n", | 1082 | dev_dbg(codec->dev, "ReTune Mobile %s tuned for %dHz\n", |
1102 | s->name, s->rate); | 1083 | s->name, s->rate); |
@@ -1139,10 +1120,9 @@ static int wm9081_digital_mute(struct snd_soc_dai *codec_dai, int mute) | |||
1139 | return 0; | 1120 | return 0; |
1140 | } | 1121 | } |
1141 | 1122 | ||
1142 | static int wm9081_set_sysclk(struct snd_soc_dai *codec_dai, | 1123 | static int wm9081_set_sysclk(struct snd_soc_codec *codec, |
1143 | int clk_id, unsigned int freq, int dir) | 1124 | int clk_id, unsigned int freq, int dir) |
1144 | { | 1125 | { |
1145 | struct snd_soc_codec *codec = codec_dai->codec; | ||
1146 | struct wm9081_priv *wm9081 = snd_soc_codec_get_drvdata(codec); | 1126 | struct wm9081_priv *wm9081 = snd_soc_codec_get_drvdata(codec); |
1147 | 1127 | ||
1148 | switch (clk_id) { | 1128 | switch (clk_id) { |
@@ -1207,7 +1187,6 @@ static int wm9081_set_tdm_slot(struct snd_soc_dai *dai, | |||
1207 | 1187 | ||
1208 | static struct snd_soc_dai_ops wm9081_dai_ops = { | 1188 | static struct snd_soc_dai_ops wm9081_dai_ops = { |
1209 | .hw_params = wm9081_hw_params, | 1189 | .hw_params = wm9081_hw_params, |
1210 | .set_sysclk = wm9081_set_sysclk, | ||
1211 | .set_fmt = wm9081_set_dai_fmt, | 1190 | .set_fmt = wm9081_set_dai_fmt, |
1212 | .digital_mute = wm9081_digital_mute, | 1191 | .digital_mute = wm9081_digital_mute, |
1213 | .set_tdm_slot = wm9081_set_tdm_slot, | 1192 | .set_tdm_slot = wm9081_set_tdm_slot, |
@@ -1231,7 +1210,6 @@ static struct snd_soc_dai_driver wm9081_dai = { | |||
1231 | static int wm9081_probe(struct snd_soc_codec *codec) | 1210 | static int wm9081_probe(struct snd_soc_codec *codec) |
1232 | { | 1211 | { |
1233 | struct wm9081_priv *wm9081 = snd_soc_codec_get_drvdata(codec); | 1212 | struct wm9081_priv *wm9081 = snd_soc_codec_get_drvdata(codec); |
1234 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
1235 | int ret; | 1213 | int ret; |
1236 | u16 reg; | 1214 | u16 reg; |
1237 | 1215 | ||
@@ -1255,6 +1233,14 @@ static int wm9081_probe(struct snd_soc_codec *codec) | |||
1255 | return ret; | 1233 | return ret; |
1256 | } | 1234 | } |
1257 | 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 | |||
1258 | wm9081_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 1244 | wm9081_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
1259 | 1245 | ||
1260 | /* Enable zero cross by default */ | 1246 | /* Enable zero cross by default */ |
@@ -1266,17 +1252,13 @@ static int wm9081_probe(struct snd_soc_codec *codec) | |||
1266 | 1252 | ||
1267 | snd_soc_add_controls(codec, wm9081_snd_controls, | 1253 | snd_soc_add_controls(codec, wm9081_snd_controls, |
1268 | ARRAY_SIZE(wm9081_snd_controls)); | 1254 | ARRAY_SIZE(wm9081_snd_controls)); |
1269 | if (!wm9081->retune) { | 1255 | if (!wm9081->pdata.num_retune_configs) { |
1270 | dev_dbg(codec->dev, | 1256 | dev_dbg(codec->dev, |
1271 | "No ReTune Mobile data, using normal EQ\n"); | 1257 | "No ReTune Mobile data, using normal EQ\n"); |
1272 | snd_soc_add_controls(codec, wm9081_eq_controls, | 1258 | snd_soc_add_controls(codec, wm9081_eq_controls, |
1273 | ARRAY_SIZE(wm9081_eq_controls)); | 1259 | ARRAY_SIZE(wm9081_eq_controls)); |
1274 | } | 1260 | } |
1275 | 1261 | ||
1276 | snd_soc_dapm_new_controls(dapm, wm9081_dapm_widgets, | ||
1277 | ARRAY_SIZE(wm9081_dapm_widgets)); | ||
1278 | snd_soc_dapm_add_routes(dapm, audio_paths, ARRAY_SIZE(audio_paths)); | ||
1279 | |||
1280 | return ret; | 1262 | return ret; |
1281 | } | 1263 | } |
1282 | 1264 | ||
@@ -1320,11 +1302,19 @@ static struct snd_soc_codec_driver soc_codec_dev_wm9081 = { | |||
1320 | .remove = wm9081_remove, | 1302 | .remove = wm9081_remove, |
1321 | .suspend = wm9081_suspend, | 1303 | .suspend = wm9081_suspend, |
1322 | .resume = wm9081_resume, | 1304 | .resume = wm9081_resume, |
1305 | |||
1306 | .set_sysclk = wm9081_set_sysclk, | ||
1323 | .set_bias_level = wm9081_set_bias_level, | 1307 | .set_bias_level = wm9081_set_bias_level, |
1308 | |||
1324 | .reg_cache_size = ARRAY_SIZE(wm9081_reg_defaults), | 1309 | .reg_cache_size = ARRAY_SIZE(wm9081_reg_defaults), |
1325 | .reg_word_size = sizeof(u16), | 1310 | .reg_word_size = sizeof(u16), |
1326 | .reg_cache_default = wm9081_reg_defaults, | 1311 | .reg_cache_default = wm9081_reg_defaults, |
1327 | .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), | ||
1328 | }; | 1318 | }; |
1329 | 1319 | ||
1330 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 1320 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
@@ -1343,8 +1333,8 @@ static __devinit int wm9081_i2c_probe(struct i2c_client *i2c, | |||
1343 | wm9081->control_data = i2c; | 1333 | wm9081->control_data = i2c; |
1344 | 1334 | ||
1345 | if (dev_get_platdata(&i2c->dev)) | 1335 | if (dev_get_platdata(&i2c->dev)) |
1346 | memcpy(&wm9081->retune, dev_get_platdata(&i2c->dev), | 1336 | memcpy(&wm9081->pdata, dev_get_platdata(&i2c->dev), |
1347 | sizeof(wm9081->retune)); | 1337 | sizeof(wm9081->pdata)); |
1348 | 1338 | ||
1349 | ret = snd_soc_register_codec(&i2c->dev, | 1339 | ret = snd_soc_register_codec(&i2c->dev, |
1350 | &soc_codec_dev_wm9081, &wm9081_dai, 1); | 1340 | &soc_codec_dev_wm9081, &wm9081_dai, 1); |
@@ -1368,7 +1358,7 @@ MODULE_DEVICE_TABLE(i2c, wm9081_i2c_id); | |||
1368 | 1358 | ||
1369 | static struct i2c_driver wm9081_i2c_driver = { | 1359 | static struct i2c_driver wm9081_i2c_driver = { |
1370 | .driver = { | 1360 | .driver = { |
1371 | .name = "wm9081-codec", | 1361 | .name = "wm9081", |
1372 | .owner = THIS_MODULE, | 1362 | .owner = THIS_MODULE, |
1373 | }, | 1363 | }, |
1374 | .probe = wm9081_i2c_probe, | 1364 | .probe = wm9081_i2c_probe, |