diff options
| -rw-r--r-- | sound/soc/codecs/wm8753.c | 54 | 
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 | ||
| 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,15 +1447,6 @@ 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) | 1450 | static 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 */ | 
| 1503 | static int wm8753_remove(struct snd_soc_codec *codec) | 1498 | static 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; | 
