diff options
Diffstat (limited to 'sound/soc/codecs/wm8993.c')
-rw-r--r-- | sound/soc/codecs/wm8993.c | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c index 5e32f2ed5fc2..cd2bc05f78cc 100644 --- a/sound/soc/codecs/wm8993.c +++ b/sound/soc/codecs/wm8993.c | |||
@@ -227,6 +227,7 @@ struct wm8993_priv { | |||
227 | int class_w_users; | 227 | int class_w_users; |
228 | unsigned int fll_fref; | 228 | unsigned int fll_fref; |
229 | unsigned int fll_fout; | 229 | unsigned int fll_fout; |
230 | int fll_src; | ||
230 | }; | 231 | }; |
231 | 232 | ||
232 | static unsigned int wm8993_read_hw(struct snd_soc_codec *codec, u8 reg) | 233 | static unsigned int wm8993_read_hw(struct snd_soc_codec *codec, u8 reg) |
@@ -506,6 +507,7 @@ static int wm8993_set_fll(struct snd_soc_dai *dai, int fll_id, int source, | |||
506 | 507 | ||
507 | wm8993->fll_fref = Fref; | 508 | wm8993->fll_fref = Fref; |
508 | wm8993->fll_fout = Fout; | 509 | wm8993->fll_fout = Fout; |
510 | wm8993->fll_src = source; | ||
509 | 511 | ||
510 | return 0; | 512 | return 0; |
511 | } | 513 | } |
@@ -1480,9 +1482,74 @@ static int wm8993_remove(struct platform_device *pdev) | |||
1480 | return 0; | 1482 | return 0; |
1481 | } | 1483 | } |
1482 | 1484 | ||
1485 | #ifdef CONFIG_PM | ||
1486 | static int wm8993_suspend(struct platform_device *pdev, pm_message_t state) | ||
1487 | { | ||
1488 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1489 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1490 | struct wm8993_priv *wm8993 = codec->private_data; | ||
1491 | int fll_fout = wm8993->fll_fout; | ||
1492 | int fll_fref = wm8993->fll_fref; | ||
1493 | int ret; | ||
1494 | |||
1495 | /* Stop the FLL in an orderly fashion */ | ||
1496 | ret = wm8993_set_fll(codec->dai, 0, 0, 0, 0); | ||
1497 | if (ret != 0) { | ||
1498 | dev_err(&pdev->dev, "Failed to stop FLL\n"); | ||
1499 | return ret; | ||
1500 | } | ||
1501 | |||
1502 | wm8993->fll_fout = fll_fout; | ||
1503 | wm8993->fll_fref = fll_fref; | ||
1504 | |||
1505 | wm8993_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1506 | |||
1507 | return 0; | ||
1508 | } | ||
1509 | |||
1510 | static int wm8993_resume(struct platform_device *pdev) | ||
1511 | { | ||
1512 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
1513 | struct snd_soc_codec *codec = socdev->card->codec; | ||
1514 | struct wm8993_priv *wm8993 = codec->private_data; | ||
1515 | u16 *cache = wm8993->reg_cache; | ||
1516 | int i, ret; | ||
1517 | |||
1518 | /* Restore the register settings */ | ||
1519 | for (i = 1; i < WM8993_MAX_REGISTER; i++) { | ||
1520 | if (cache[i] == wm8993_reg_defaults[i]) | ||
1521 | continue; | ||
1522 | snd_soc_write(codec, i, cache[i]); | ||
1523 | } | ||
1524 | |||
1525 | wm8993_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1526 | |||
1527 | /* Restart the FLL? */ | ||
1528 | if (wm8993->fll_fout) { | ||
1529 | int fll_fout = wm8993->fll_fout; | ||
1530 | int fll_fref = wm8993->fll_fref; | ||
1531 | |||
1532 | wm8993->fll_fref = 0; | ||
1533 | wm8993->fll_fout = 0; | ||
1534 | |||
1535 | ret = wm8993_set_fll(codec->dai, 0, wm8993->fll_src, | ||
1536 | fll_fref, fll_fout); | ||
1537 | if (ret != 0) | ||
1538 | dev_err(codec->dev, "Failed to restart FLL\n"); | ||
1539 | } | ||
1540 | |||
1541 | return 0; | ||
1542 | } | ||
1543 | #else | ||
1544 | #define wm8993_suspend NULL | ||
1545 | #define wm8993_resume NULL | ||
1546 | #endif | ||
1547 | |||
1483 | struct snd_soc_codec_device soc_codec_dev_wm8993 = { | 1548 | struct snd_soc_codec_device soc_codec_dev_wm8993 = { |
1484 | .probe = wm8993_probe, | 1549 | .probe = wm8993_probe, |
1485 | .remove = wm8993_remove, | 1550 | .remove = wm8993_remove, |
1551 | .suspend = wm8993_suspend, | ||
1552 | .resume = wm8993_resume, | ||
1486 | }; | 1553 | }; |
1487 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8993); | 1554 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8993); |
1488 | 1555 | ||