diff options
author | Mark Brown <broonie@kernel.org> | 2015-04-12 14:48:30 -0400 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2015-04-12 14:48:30 -0400 |
commit | d1113af4e8c0f2cd71e52cb904447bd0eec8aa54 (patch) | |
tree | 60de96c5b9716f6115ed68507c0deb361d063569 /sound/soc/codecs | |
parent | 89a88dd3d6823f46bfb1405c4b358f89d5526cd6 (diff) | |
parent | a5053a8e200e865ab786384df3f985a3cbb346fe (diff) |
Merge remote-tracking branch 'asoc/topic/core' into asoc-next
Diffstat (limited to 'sound/soc/codecs')
-rw-r--r-- | sound/soc/codecs/wm8350.c | 25 | ||||
-rw-r--r-- | sound/soc/codecs/wm8753.c | 73 | ||||
-rw-r--r-- | sound/soc/codecs/wm8971.c | 99 |
3 files changed, 66 insertions, 131 deletions
diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c index c81a9eab3e3e..c65e5a75fc1a 100644 --- a/sound/soc/codecs/wm8350.c +++ b/sound/soc/codecs/wm8350.c | |||
@@ -69,14 +69,14 @@ struct wm8350_data { | |||
69 | struct regulator_bulk_data supplies[ARRAY_SIZE(supply_names)]; | 69 | struct regulator_bulk_data supplies[ARRAY_SIZE(supply_names)]; |
70 | int fll_freq_out; | 70 | int fll_freq_out; |
71 | int fll_freq_in; | 71 | int fll_freq_in; |
72 | struct delayed_work pga_work; | ||
72 | }; | 73 | }; |
73 | 74 | ||
74 | /* | 75 | /* |
75 | * Ramp OUT1 PGA volume to minimise pops at stream startup and shutdown. | 76 | * Ramp OUT1 PGA volume to minimise pops at stream startup and shutdown. |
76 | */ | 77 | */ |
77 | static inline int wm8350_out1_ramp_step(struct snd_soc_codec *codec) | 78 | static inline int wm8350_out1_ramp_step(struct wm8350_data *wm8350_data) |
78 | { | 79 | { |
79 | struct wm8350_data *wm8350_data = snd_soc_codec_get_drvdata(codec); | ||
80 | struct wm8350_output *out1 = &wm8350_data->out1; | 80 | struct wm8350_output *out1 = &wm8350_data->out1; |
81 | struct wm8350 *wm8350 = wm8350_data->wm8350; | 81 | struct wm8350 *wm8350 = wm8350_data->wm8350; |
82 | int left_complete = 0, right_complete = 0; | 82 | int left_complete = 0, right_complete = 0; |
@@ -140,9 +140,8 @@ static inline int wm8350_out1_ramp_step(struct snd_soc_codec *codec) | |||
140 | /* | 140 | /* |
141 | * Ramp OUT2 PGA volume to minimise pops at stream startup and shutdown. | 141 | * Ramp OUT2 PGA volume to minimise pops at stream startup and shutdown. |
142 | */ | 142 | */ |
143 | static inline int wm8350_out2_ramp_step(struct snd_soc_codec *codec) | 143 | static inline int wm8350_out2_ramp_step(struct wm8350_data *wm8350_data) |
144 | { | 144 | { |
145 | struct wm8350_data *wm8350_data = snd_soc_codec_get_drvdata(codec); | ||
146 | struct wm8350_output *out2 = &wm8350_data->out2; | 145 | struct wm8350_output *out2 = &wm8350_data->out2; |
147 | struct wm8350 *wm8350 = wm8350_data->wm8350; | 146 | struct wm8350 *wm8350 = wm8350_data->wm8350; |
148 | int left_complete = 0, right_complete = 0; | 147 | int left_complete = 0, right_complete = 0; |
@@ -210,10 +209,8 @@ static inline int wm8350_out2_ramp_step(struct snd_soc_codec *codec) | |||
210 | */ | 209 | */ |
211 | static void wm8350_pga_work(struct work_struct *work) | 210 | static void wm8350_pga_work(struct work_struct *work) |
212 | { | 211 | { |
213 | struct snd_soc_dapm_context *dapm = | 212 | struct wm8350_data *wm8350_data = |
214 | container_of(work, struct snd_soc_dapm_context, delayed_work.work); | 213 | container_of(work, struct wm8350_data, pga_work.work); |
215 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(dapm); | ||
216 | struct wm8350_data *wm8350_data = snd_soc_codec_get_drvdata(codec); | ||
217 | struct wm8350_output *out1 = &wm8350_data->out1, | 214 | struct wm8350_output *out1 = &wm8350_data->out1, |
218 | *out2 = &wm8350_data->out2; | 215 | *out2 = &wm8350_data->out2; |
219 | int i, out1_complete, out2_complete; | 216 | int i, out1_complete, out2_complete; |
@@ -226,9 +223,9 @@ static void wm8350_pga_work(struct work_struct *work) | |||
226 | for (i = 0; i <= 63; i++) { | 223 | for (i = 0; i <= 63; i++) { |
227 | out1_complete = 1, out2_complete = 1; | 224 | out1_complete = 1, out2_complete = 1; |
228 | if (out1->ramp != WM8350_RAMP_NONE) | 225 | if (out1->ramp != WM8350_RAMP_NONE) |
229 | out1_complete = wm8350_out1_ramp_step(codec); | 226 | out1_complete = wm8350_out1_ramp_step(wm8350_data); |
230 | if (out2->ramp != WM8350_RAMP_NONE) | 227 | if (out2->ramp != WM8350_RAMP_NONE) |
231 | out2_complete = wm8350_out2_ramp_step(codec); | 228 | out2_complete = wm8350_out2_ramp_step(wm8350_data); |
232 | 229 | ||
233 | /* ramp finished ? */ | 230 | /* ramp finished ? */ |
234 | if (out1_complete && out2_complete) | 231 | if (out1_complete && out2_complete) |
@@ -283,7 +280,7 @@ static int pga_event(struct snd_soc_dapm_widget *w, | |||
283 | out->ramp = WM8350_RAMP_UP; | 280 | out->ramp = WM8350_RAMP_UP; |
284 | out->active = 1; | 281 | out->active = 1; |
285 | 282 | ||
286 | schedule_delayed_work(&codec->dapm.delayed_work, | 283 | schedule_delayed_work(&wm8350_data->pga_work, |
287 | msecs_to_jiffies(1)); | 284 | msecs_to_jiffies(1)); |
288 | break; | 285 | break; |
289 | 286 | ||
@@ -291,7 +288,7 @@ static int pga_event(struct snd_soc_dapm_widget *w, | |||
291 | out->ramp = WM8350_RAMP_DOWN; | 288 | out->ramp = WM8350_RAMP_DOWN; |
292 | out->active = 0; | 289 | out->active = 0; |
293 | 290 | ||
294 | schedule_delayed_work(&codec->dapm.delayed_work, | 291 | schedule_delayed_work(&wm8350_data->pga_work, |
295 | msecs_to_jiffies(1)); | 292 | msecs_to_jiffies(1)); |
296 | break; | 293 | break; |
297 | } | 294 | } |
@@ -1492,7 +1489,7 @@ static int wm8350_codec_probe(struct snd_soc_codec *codec) | |||
1492 | /* Put the codec into reset if it wasn't already */ | 1489 | /* Put the codec into reset if it wasn't already */ |
1493 | wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA); | 1490 | wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA); |
1494 | 1491 | ||
1495 | INIT_DELAYED_WORK(&codec->dapm.delayed_work, wm8350_pga_work); | 1492 | INIT_DELAYED_WORK(&priv->pga_work, wm8350_pga_work); |
1496 | INIT_DELAYED_WORK(&priv->hpl.work, wm8350_hpl_work); | 1493 | INIT_DELAYED_WORK(&priv->hpl.work, wm8350_hpl_work); |
1497 | INIT_DELAYED_WORK(&priv->hpr.work, wm8350_hpr_work); | 1494 | INIT_DELAYED_WORK(&priv->hpr.work, wm8350_hpr_work); |
1498 | 1495 | ||
@@ -1578,7 +1575,7 @@ static int wm8350_codec_remove(struct snd_soc_codec *codec) | |||
1578 | 1575 | ||
1579 | /* if there was any work waiting then we run it now and | 1576 | /* if there was any work waiting then we run it now and |
1580 | * wait for its completion */ | 1577 | * wait for its completion */ |
1581 | flush_delayed_work(&codec->dapm.delayed_work); | 1578 | flush_delayed_work(&priv->pga_work); |
1582 | 1579 | ||
1583 | wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA); | 1580 | wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA); |
1584 | 1581 | ||
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c index 21ca3a94fc96..c50a5959345f 100644 --- a/sound/soc/codecs/wm8753.c +++ b/sound/soc/codecs/wm8753.c | |||
@@ -153,6 +153,7 @@ struct wm8753_priv { | |||
153 | unsigned int hifi_fmt; | 153 | unsigned int hifi_fmt; |
154 | 154 | ||
155 | int dai_func; | 155 | int dai_func; |
156 | struct delayed_work charge_work; | ||
156 | }; | 157 | }; |
157 | 158 | ||
158 | #define wm8753_reset(c) snd_soc_write(c, WM8753_RESET, 0) | 159 | #define wm8753_reset(c) snd_soc_write(c, WM8753_RESET, 0) |
@@ -1326,9 +1327,19 @@ static int wm8753_mute(struct snd_soc_dai *dai, int mute) | |||
1326 | return 0; | 1327 | return 0; |
1327 | } | 1328 | } |
1328 | 1329 | ||
1330 | static void wm8753_charge_work(struct work_struct *work) | ||
1331 | { | ||
1332 | struct wm8753_priv *wm8753 = | ||
1333 | container_of(work, struct wm8753_priv, charge_work.work); | ||
1334 | |||
1335 | /* Set to 500k */ | ||
1336 | regmap_update_bits(wm8753->regmap, WM8753_PWR1, 0x0180, 0x0100); | ||
1337 | } | ||
1338 | |||
1329 | static int wm8753_set_bias_level(struct snd_soc_codec *codec, | 1339 | static int wm8753_set_bias_level(struct snd_soc_codec *codec, |
1330 | enum snd_soc_bias_level level) | 1340 | enum snd_soc_bias_level level) |
1331 | { | 1341 | { |
1342 | struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); | ||
1332 | u16 pwr_reg = snd_soc_read(codec, WM8753_PWR1) & 0xfe3e; | 1343 | u16 pwr_reg = snd_soc_read(codec, WM8753_PWR1) & 0xfe3e; |
1333 | 1344 | ||
1334 | switch (level) { | 1345 | switch (level) { |
@@ -1337,14 +1348,22 @@ static int wm8753_set_bias_level(struct snd_soc_codec *codec, | |||
1337 | snd_soc_write(codec, WM8753_PWR1, pwr_reg | 0x00c0); | 1348 | snd_soc_write(codec, WM8753_PWR1, pwr_reg | 0x00c0); |
1338 | break; | 1349 | break; |
1339 | case SND_SOC_BIAS_PREPARE: | 1350 | case SND_SOC_BIAS_PREPARE: |
1340 | /* set vmid to 5k for quick power up */ | 1351 | /* Wait until fully charged */ |
1341 | snd_soc_write(codec, WM8753_PWR1, pwr_reg | 0x01c1); | 1352 | flush_delayed_work(&wm8753->charge_work); |
1342 | break; | 1353 | break; |
1343 | case SND_SOC_BIAS_STANDBY: | 1354 | case SND_SOC_BIAS_STANDBY: |
1344 | /* mute dac and set vmid to 500k, enable VREF */ | 1355 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { |
1345 | snd_soc_write(codec, WM8753_PWR1, pwr_reg | 0x0141); | 1356 | /* set vmid to 5k for quick power up */ |
1357 | snd_soc_write(codec, WM8753_PWR1, pwr_reg | 0x01c1); | ||
1358 | schedule_delayed_work(&wm8753->charge_work, | ||
1359 | msecs_to_jiffies(caps_charge)); | ||
1360 | } else { | ||
1361 | /* mute dac and set vmid to 500k, enable VREF */ | ||
1362 | snd_soc_write(codec, WM8753_PWR1, pwr_reg | 0x0141); | ||
1363 | } | ||
1346 | break; | 1364 | break; |
1347 | case SND_SOC_BIAS_OFF: | 1365 | case SND_SOC_BIAS_OFF: |
1366 | cancel_delayed_work_sync(&wm8753->charge_work); | ||
1348 | snd_soc_write(codec, WM8753_PWR1, 0x0001); | 1367 | snd_soc_write(codec, WM8753_PWR1, 0x0001); |
1349 | break; | 1368 | break; |
1350 | } | 1369 | } |
@@ -1428,38 +1447,12 @@ static struct snd_soc_dai_driver wm8753_dai[] = { | |||
1428 | }, | 1447 | }, |
1429 | }; | 1448 | }; |
1430 | 1449 | ||
1431 | static void wm8753_work(struct work_struct *work) | ||
1432 | { | ||
1433 | struct snd_soc_dapm_context *dapm = | ||
1434 | container_of(work, struct snd_soc_dapm_context, | ||
1435 | delayed_work.work); | ||
1436 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(dapm); | ||
1437 | wm8753_set_bias_level(codec, dapm->bias_level); | ||
1438 | } | ||
1439 | |||
1440 | static int wm8753_suspend(struct snd_soc_codec *codec) | ||
1441 | { | ||
1442 | wm8753_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1443 | return 0; | ||
1444 | } | ||
1445 | |||
1446 | static int wm8753_resume(struct snd_soc_codec *codec) | 1450 | static int wm8753_resume(struct snd_soc_codec *codec) |
1447 | { | 1451 | { |
1448 | struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); | 1452 | struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); |
1449 | 1453 | ||
1450 | regcache_sync(wm8753->regmap); | 1454 | regcache_sync(wm8753->regmap); |
1451 | 1455 | ||
1452 | wm8753_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1453 | |||
1454 | /* charge wm8753 caps */ | ||
1455 | if (codec->dapm.suspend_bias_level == SND_SOC_BIAS_ON) { | ||
1456 | wm8753_set_bias_level(codec, SND_SOC_BIAS_PREPARE); | ||
1457 | codec->dapm.bias_level = SND_SOC_BIAS_ON; | ||
1458 | queue_delayed_work(system_power_efficient_wq, | ||
1459 | &codec->dapm.delayed_work, | ||
1460 | msecs_to_jiffies(caps_charge)); | ||
1461 | } | ||
1462 | |||
1463 | return 0; | 1456 | return 0; |
1464 | } | 1457 | } |
1465 | 1458 | ||
@@ -1468,7 +1461,7 @@ static int wm8753_probe(struct snd_soc_codec *codec) | |||
1468 | struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); | 1461 | struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); |
1469 | int ret; | 1462 | int ret; |
1470 | 1463 | ||
1471 | INIT_DELAYED_WORK(&codec->dapm.delayed_work, wm8753_work); | 1464 | INIT_DELAYED_WORK(&wm8753->charge_work, wm8753_charge_work); |
1472 | 1465 | ||
1473 | ret = wm8753_reset(codec); | 1466 | ret = wm8753_reset(codec); |
1474 | if (ret < 0) { | 1467 | if (ret < 0) { |
@@ -1476,14 +1469,8 @@ static int wm8753_probe(struct snd_soc_codec *codec) | |||
1476 | return ret; | 1469 | return ret; |
1477 | } | 1470 | } |
1478 | 1471 | ||
1479 | wm8753_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1480 | wm8753->dai_func = 0; | 1472 | wm8753->dai_func = 0; |
1481 | 1473 | ||
1482 | /* charge output caps */ | ||
1483 | wm8753_set_bias_level(codec, SND_SOC_BIAS_PREPARE); | ||
1484 | schedule_delayed_work(&codec->dapm.delayed_work, | ||
1485 | msecs_to_jiffies(caps_charge)); | ||
1486 | |||
1487 | /* set the update bits */ | 1474 | /* set the update bits */ |
1488 | snd_soc_update_bits(codec, WM8753_LDAC, 0x0100, 0x0100); | 1475 | snd_soc_update_bits(codec, WM8753_LDAC, 0x0100, 0x0100); |
1489 | snd_soc_update_bits(codec, WM8753_RDAC, 0x0100, 0x0100); | 1476 | snd_soc_update_bits(codec, WM8753_RDAC, 0x0100, 0x0100); |
@@ -1499,21 +1486,11 @@ static int wm8753_probe(struct snd_soc_codec *codec) | |||
1499 | return 0; | 1486 | return 0; |
1500 | } | 1487 | } |
1501 | 1488 | ||
1502 | /* power down chip */ | ||
1503 | static int wm8753_remove(struct snd_soc_codec *codec) | ||
1504 | { | ||
1505 | flush_delayed_work(&codec->dapm.delayed_work); | ||
1506 | wm8753_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1507 | |||
1508 | return 0; | ||
1509 | } | ||
1510 | |||
1511 | static struct snd_soc_codec_driver soc_codec_dev_wm8753 = { | 1489 | static struct snd_soc_codec_driver soc_codec_dev_wm8753 = { |
1512 | .probe = wm8753_probe, | 1490 | .probe = wm8753_probe, |
1513 | .remove = wm8753_remove, | ||
1514 | .suspend = wm8753_suspend, | ||
1515 | .resume = wm8753_resume, | 1491 | .resume = wm8753_resume, |
1516 | .set_bias_level = wm8753_set_bias_level, | 1492 | .set_bias_level = wm8753_set_bias_level, |
1493 | .suspend_bias_off = true, | ||
1517 | 1494 | ||
1518 | .controls = wm8753_snd_controls, | 1495 | .controls = wm8753_snd_controls, |
1519 | .num_controls = ARRAY_SIZE(wm8753_snd_controls), | 1496 | .num_controls = ARRAY_SIZE(wm8753_snd_controls), |
diff --git a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c index 39ddb9b8834c..f9cbabdc6238 100644 --- a/sound/soc/codecs/wm8971.c +++ b/sound/soc/codecs/wm8971.c | |||
@@ -31,11 +31,11 @@ | |||
31 | 31 | ||
32 | #define WM8971_REG_COUNT 43 | 32 | #define WM8971_REG_COUNT 43 |
33 | 33 | ||
34 | static struct workqueue_struct *wm8971_workq = NULL; | ||
35 | |||
36 | /* codec private data */ | 34 | /* codec private data */ |
37 | struct wm8971_priv { | 35 | struct wm8971_priv { |
38 | unsigned int sysclk; | 36 | unsigned int sysclk; |
37 | struct delayed_work charge_work; | ||
38 | struct regmap *regmap; | ||
39 | }; | 39 | }; |
40 | 40 | ||
41 | /* | 41 | /* |
@@ -552,9 +552,19 @@ static int wm8971_mute(struct snd_soc_dai *dai, int mute) | |||
552 | return 0; | 552 | return 0; |
553 | } | 553 | } |
554 | 554 | ||
555 | static void wm8971_charge_work(struct work_struct *work) | ||
556 | { | ||
557 | struct wm8971_priv *wm8971 = | ||
558 | container_of(work, struct wm8971_priv, charge_work.work); | ||
559 | |||
560 | /* Set to 500k */ | ||
561 | regmap_update_bits(wm8971->regmap, WM8971_PWR1, 0x0180, 0x0100); | ||
562 | } | ||
563 | |||
555 | static int wm8971_set_bias_level(struct snd_soc_codec *codec, | 564 | static int wm8971_set_bias_level(struct snd_soc_codec *codec, |
556 | enum snd_soc_bias_level level) | 565 | enum snd_soc_bias_level level) |
557 | { | 566 | { |
567 | struct wm8971_priv *wm8971 = snd_soc_codec_get_drvdata(codec); | ||
558 | u16 pwr_reg = snd_soc_read(codec, WM8971_PWR1) & 0xfe3e; | 568 | u16 pwr_reg = snd_soc_read(codec, WM8971_PWR1) & 0xfe3e; |
559 | 569 | ||
560 | switch (level) { | 570 | switch (level) { |
@@ -563,15 +573,24 @@ static int wm8971_set_bias_level(struct snd_soc_codec *codec, | |||
563 | snd_soc_write(codec, WM8971_PWR1, pwr_reg | 0x00c1); | 573 | snd_soc_write(codec, WM8971_PWR1, pwr_reg | 0x00c1); |
564 | break; | 574 | break; |
565 | case SND_SOC_BIAS_PREPARE: | 575 | case SND_SOC_BIAS_PREPARE: |
576 | /* Wait until fully charged */ | ||
577 | flush_delayed_work(&wm8971->charge_work); | ||
566 | break; | 578 | break; |
567 | case SND_SOC_BIAS_STANDBY: | 579 | case SND_SOC_BIAS_STANDBY: |
568 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) | 580 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { |
569 | snd_soc_cache_sync(codec); | 581 | snd_soc_cache_sync(codec); |
582 | /* charge output caps - set vmid to 5k for quick power up */ | ||
583 | snd_soc_write(codec, WM8971_PWR1, pwr_reg | 0x01c0); | ||
584 | queue_delayed_work(system_power_efficient_wq, | ||
585 | &wm8971->charge_work, msecs_to_jiffies(1000)); | ||
586 | } else { | ||
587 | /* mute dac and set vmid to 500k, enable VREF */ | ||
588 | snd_soc_write(codec, WM8971_PWR1, pwr_reg | 0x0140); | ||
589 | } | ||
570 | 590 | ||
571 | /* mute dac and set vmid to 500k, enable VREF */ | ||
572 | snd_soc_write(codec, WM8971_PWR1, pwr_reg | 0x0140); | ||
573 | break; | 591 | break; |
574 | case SND_SOC_BIAS_OFF: | 592 | case SND_SOC_BIAS_OFF: |
593 | cancel_delayed_work_sync(&wm8971->charge_work); | ||
575 | snd_soc_write(codec, WM8971_PWR1, 0x0001); | 594 | snd_soc_write(codec, WM8971_PWR1, 0x0001); |
576 | break; | 595 | break; |
577 | } | 596 | } |
@@ -610,58 +629,14 @@ static struct snd_soc_dai_driver wm8971_dai = { | |||
610 | .ops = &wm8971_dai_ops, | 629 | .ops = &wm8971_dai_ops, |
611 | }; | 630 | }; |
612 | 631 | ||
613 | static void wm8971_work(struct work_struct *work) | ||
614 | { | ||
615 | struct snd_soc_dapm_context *dapm = | ||
616 | container_of(work, struct snd_soc_dapm_context, | ||
617 | delayed_work.work); | ||
618 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(dapm); | ||
619 | wm8971_set_bias_level(codec, codec->dapm.bias_level); | ||
620 | } | ||
621 | |||
622 | static int wm8971_suspend(struct snd_soc_codec *codec) | ||
623 | { | ||
624 | wm8971_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
625 | return 0; | ||
626 | } | ||
627 | |||
628 | static int wm8971_resume(struct snd_soc_codec *codec) | ||
629 | { | ||
630 | u16 reg; | ||
631 | |||
632 | wm8971_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
633 | |||
634 | /* charge wm8971 caps */ | ||
635 | if (codec->dapm.suspend_bias_level == SND_SOC_BIAS_ON) { | ||
636 | reg = snd_soc_read(codec, WM8971_PWR1) & 0xfe3e; | ||
637 | snd_soc_write(codec, WM8971_PWR1, reg | 0x01c0); | ||
638 | codec->dapm.bias_level = SND_SOC_BIAS_ON; | ||
639 | queue_delayed_work(wm8971_workq, &codec->dapm.delayed_work, | ||
640 | msecs_to_jiffies(1000)); | ||
641 | } | ||
642 | |||
643 | return 0; | ||
644 | } | ||
645 | |||
646 | static int wm8971_probe(struct snd_soc_codec *codec) | 632 | static int wm8971_probe(struct snd_soc_codec *codec) |
647 | { | 633 | { |
648 | int ret = 0; | 634 | struct wm8971_priv *wm8971 = snd_soc_codec_get_drvdata(codec); |
649 | u16 reg; | ||
650 | 635 | ||
651 | INIT_DELAYED_WORK(&codec->dapm.delayed_work, wm8971_work); | 636 | INIT_DELAYED_WORK(&wm8971->charge_work, wm8971_charge_work); |
652 | wm8971_workq = create_workqueue("wm8971"); | ||
653 | if (wm8971_workq == NULL) | ||
654 | return -ENOMEM; | ||
655 | 637 | ||
656 | wm8971_reset(codec); | 638 | wm8971_reset(codec); |
657 | 639 | ||
658 | /* charge output caps - set vmid to 5k for quick power up */ | ||
659 | reg = snd_soc_read(codec, WM8971_PWR1) & 0xfe3e; | ||
660 | snd_soc_write(codec, WM8971_PWR1, reg | 0x01c0); | ||
661 | codec->dapm.bias_level = SND_SOC_BIAS_STANDBY; | ||
662 | queue_delayed_work(wm8971_workq, &codec->dapm.delayed_work, | ||
663 | msecs_to_jiffies(1000)); | ||
664 | |||
665 | /* set the update bits */ | 640 | /* set the update bits */ |
666 | snd_soc_update_bits(codec, WM8971_LDAC, 0x0100, 0x0100); | 641 | snd_soc_update_bits(codec, WM8971_LDAC, 0x0100, 0x0100); |
667 | snd_soc_update_bits(codec, WM8971_RDAC, 0x0100, 0x0100); | 642 | snd_soc_update_bits(codec, WM8971_RDAC, 0x0100, 0x0100); |
@@ -672,26 +647,13 @@ static int wm8971_probe(struct snd_soc_codec *codec) | |||
672 | snd_soc_update_bits(codec, WM8971_LINVOL, 0x0100, 0x0100); | 647 | snd_soc_update_bits(codec, WM8971_LINVOL, 0x0100, 0x0100); |
673 | snd_soc_update_bits(codec, WM8971_RINVOL, 0x0100, 0x0100); | 648 | snd_soc_update_bits(codec, WM8971_RINVOL, 0x0100, 0x0100); |
674 | 649 | ||
675 | return ret; | ||
676 | } | ||
677 | |||
678 | |||
679 | /* power down chip */ | ||
680 | static int wm8971_remove(struct snd_soc_codec *codec) | ||
681 | { | ||
682 | wm8971_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
683 | |||
684 | if (wm8971_workq) | ||
685 | destroy_workqueue(wm8971_workq); | ||
686 | return 0; | 650 | return 0; |
687 | } | 651 | } |
688 | 652 | ||
689 | static struct snd_soc_codec_driver soc_codec_dev_wm8971 = { | 653 | static struct snd_soc_codec_driver soc_codec_dev_wm8971 = { |
690 | .probe = wm8971_probe, | 654 | .probe = wm8971_probe, |
691 | .remove = wm8971_remove, | ||
692 | .suspend = wm8971_suspend, | ||
693 | .resume = wm8971_resume, | ||
694 | .set_bias_level = wm8971_set_bias_level, | 655 | .set_bias_level = wm8971_set_bias_level, |
656 | .suspend_bias_off = true, | ||
695 | 657 | ||
696 | .controls = wm8971_snd_controls, | 658 | .controls = wm8971_snd_controls, |
697 | .num_controls = ARRAY_SIZE(wm8971_snd_controls), | 659 | .num_controls = ARRAY_SIZE(wm8971_snd_controls), |
@@ -715,7 +677,6 @@ static int wm8971_i2c_probe(struct i2c_client *i2c, | |||
715 | const struct i2c_device_id *id) | 677 | const struct i2c_device_id *id) |
716 | { | 678 | { |
717 | struct wm8971_priv *wm8971; | 679 | struct wm8971_priv *wm8971; |
718 | struct regmap *regmap; | ||
719 | int ret; | 680 | int ret; |
720 | 681 | ||
721 | wm8971 = devm_kzalloc(&i2c->dev, sizeof(struct wm8971_priv), | 682 | wm8971 = devm_kzalloc(&i2c->dev, sizeof(struct wm8971_priv), |
@@ -723,9 +684,9 @@ static int wm8971_i2c_probe(struct i2c_client *i2c, | |||
723 | if (wm8971 == NULL) | 684 | if (wm8971 == NULL) |
724 | return -ENOMEM; | 685 | return -ENOMEM; |
725 | 686 | ||
726 | regmap = devm_regmap_init_i2c(i2c, &wm8971_regmap); | 687 | wm8971->regmap = devm_regmap_init_i2c(i2c, &wm8971_regmap); |
727 | if (IS_ERR(regmap)) | 688 | if (IS_ERR(wm8971->regmap)) |
728 | return PTR_ERR(regmap); | 689 | return PTR_ERR(wm8971->regmap); |
729 | 690 | ||
730 | i2c_set_clientdata(i2c, wm8971); | 691 | i2c_set_clientdata(i2c, wm8971); |
731 | 692 | ||