aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sound/soc/codecs/wm8753.c54
1 files changed, 24 insertions, 30 deletions
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c
index 21ca3a94fc96..176fcb1530c3 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
1330static 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
1329static int wm8753_set_bias_level(struct snd_soc_codec *codec, 1339static 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,15 +1447,6 @@ static struct snd_soc_dai_driver wm8753_dai[] = {
1428}, 1447},
1429}; 1448};
1430 1449
1431static 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
1440static int wm8753_suspend(struct snd_soc_codec *codec) 1450static int wm8753_suspend(struct snd_soc_codec *codec)
1441{ 1451{
1442 wm8753_set_bias_level(codec, SND_SOC_BIAS_OFF); 1452 wm8753_set_bias_level(codec, SND_SOC_BIAS_OFF);
@@ -1450,16 +1460,6 @@ static int wm8753_resume(struct snd_soc_codec *codec)
1450 regcache_sync(wm8753->regmap); 1460 regcache_sync(wm8753->regmap);
1451 1461
1452 wm8753_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 1462 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; 1463 return 0;
1464} 1464}
1465 1465
@@ -1468,7 +1468,7 @@ static int wm8753_probe(struct snd_soc_codec *codec)
1468 struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec); 1468 struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
1469 int ret; 1469 int ret;
1470 1470
1471 INIT_DELAYED_WORK(&codec->dapm.delayed_work, wm8753_work); 1471 INIT_DELAYED_WORK(&wm8753->charge_work, wm8753_charge_work);
1472 1472
1473 ret = wm8753_reset(codec); 1473 ret = wm8753_reset(codec);
1474 if (ret < 0) { 1474 if (ret < 0) {
@@ -1479,11 +1479,6 @@ static int wm8753_probe(struct snd_soc_codec *codec)
1479 wm8753_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 1479 wm8753_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1480 wm8753->dai_func = 0; 1480 wm8753->dai_func = 0;
1481 1481
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 */ 1482 /* set the update bits */
1488 snd_soc_update_bits(codec, WM8753_LDAC, 0x0100, 0x0100); 1483 snd_soc_update_bits(codec, WM8753_LDAC, 0x0100, 0x0100);
1489 snd_soc_update_bits(codec, WM8753_RDAC, 0x0100, 0x0100); 1484 snd_soc_update_bits(codec, WM8753_RDAC, 0x0100, 0x0100);
@@ -1502,7 +1497,6 @@ static int wm8753_probe(struct snd_soc_codec *codec)
1502/* power down chip */ 1497/* power down chip */
1503static int wm8753_remove(struct snd_soc_codec *codec) 1498static int wm8753_remove(struct snd_soc_codec *codec)
1504{ 1499{
1505 flush_delayed_work(&codec->dapm.delayed_work);
1506 wm8753_set_bias_level(codec, SND_SOC_BIAS_OFF); 1500 wm8753_set_bias_level(codec, SND_SOC_BIAS_OFF);
1507 1501
1508 return 0; 1502 return 0;