Skip to content

Commit e6a9750

Browse files
TE-N-ShengjiuWangbroonie
authored andcommitted
ASoC: fsl_xcvr: Add suspend and resume support
Use regcache_sync() to recover the registers of controller, PHY and PLL after suspend and resume. In order to recover the registers need to avoid use the *_SET, *_CLR and *_TOG registers. Recovery of the registers should be done before loading XCVR firmware otherwise some registers set by firmware are overwritten. Besides only in eARC mode is it necessary to load XCVR firmware. Signed-off-by: Shengjiu Wang <[email protected]> Signed-off-by: Chancel Liu <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Mark Brown <[email protected]>
1 parent 5a8b478 commit e6a9750

File tree

1 file changed

+118
-42
lines changed

1 file changed

+118
-42
lines changed

sound/soc/fsl/fsl_xcvr.c

Lines changed: 118 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -503,7 +503,7 @@ static int fsl_xcvr_prepare(struct snd_pcm_substream *substream,
503503
switch (xcvr->mode) {
504504
case FSL_XCVR_MODE_SPDIF:
505505
if (xcvr->soc_data->spdif_only && tx) {
506-
ret = regmap_update_bits(xcvr->regmap, FSL_XCVR_TX_DPTH_CTRL_SET,
506+
ret = regmap_update_bits(xcvr->regmap, FSL_XCVR_TX_DPTH_CTRL,
507507
FSL_XCVR_TX_DPTH_CTRL_BYPASS_FEM,
508508
FSL_XCVR_TX_DPTH_CTRL_BYPASS_FEM);
509509
if (ret < 0) {
@@ -521,8 +521,8 @@ static int fsl_xcvr_prepare(struct snd_pcm_substream *substream,
521521
return ret;
522522
}
523523

524-
ret = regmap_write(xcvr->regmap, FSL_XCVR_TX_DPTH_CTRL_SET,
525-
FSL_XCVR_TX_DPTH_CTRL_FRM_FMT);
524+
ret = regmap_set_bits(xcvr->regmap, FSL_XCVR_TX_DPTH_CTRL,
525+
FSL_XCVR_TX_DPTH_CTRL_FRM_FMT);
526526
if (ret < 0) {
527527
dev_err(dai->dev, "Failed to set TX_DPTH: %d\n", ret);
528528
return ret;
@@ -539,11 +539,11 @@ static int fsl_xcvr_prepare(struct snd_pcm_substream *substream,
539539
* Clear RX FIFO, flip RX FIFO bits,
540540
* disable eARC related HW mode detects
541541
*/
542-
ret = regmap_write(xcvr->regmap, FSL_XCVR_RX_DPTH_CTRL_SET,
543-
FSL_XCVR_RX_DPTH_CTRL_STORE_FMT |
544-
FSL_XCVR_RX_DPTH_CTRL_CLR_RX_FIFO |
545-
FSL_XCVR_RX_DPTH_CTRL_COMP |
546-
FSL_XCVR_RX_DPTH_CTRL_LAYB_CTRL);
542+
ret = regmap_set_bits(xcvr->regmap, FSL_XCVR_RX_DPTH_CTRL,
543+
FSL_XCVR_RX_DPTH_CTRL_STORE_FMT |
544+
FSL_XCVR_RX_DPTH_CTRL_CLR_RX_FIFO |
545+
FSL_XCVR_RX_DPTH_CTRL_COMP |
546+
FSL_XCVR_RX_DPTH_CTRL_LAYB_CTRL);
547547
if (ret < 0) {
548548
dev_err(dai->dev, "Failed to set RX_DPTH: %d\n", ret);
549549
return ret;
@@ -560,18 +560,18 @@ static int fsl_xcvr_prepare(struct snd_pcm_substream *substream,
560560
case FSL_XCVR_MODE_EARC:
561561
if (!tx) {
562562
/** Clear RX FIFO, flip RX FIFO bits */
563-
ret = regmap_write(xcvr->regmap, FSL_XCVR_RX_DPTH_CTRL_SET,
564-
FSL_XCVR_RX_DPTH_CTRL_STORE_FMT |
565-
FSL_XCVR_RX_DPTH_CTRL_CLR_RX_FIFO);
563+
ret = regmap_set_bits(xcvr->regmap, FSL_XCVR_RX_DPTH_CTRL,
564+
FSL_XCVR_RX_DPTH_CTRL_STORE_FMT |
565+
FSL_XCVR_RX_DPTH_CTRL_CLR_RX_FIFO);
566566
if (ret < 0) {
567567
dev_err(dai->dev, "Failed to set RX_DPTH: %d\n", ret);
568568
return ret;
569569
}
570570

571571
/** Enable eARC related HW mode detects */
572-
ret = regmap_write(xcvr->regmap, FSL_XCVR_RX_DPTH_CTRL_CLR,
573-
FSL_XCVR_RX_DPTH_CTRL_COMP |
574-
FSL_XCVR_RX_DPTH_CTRL_LAYB_CTRL);
572+
ret = regmap_clear_bits(xcvr->regmap, FSL_XCVR_RX_DPTH_CTRL,
573+
FSL_XCVR_RX_DPTH_CTRL_COMP |
574+
FSL_XCVR_RX_DPTH_CTRL_LAYB_CTRL);
575575
if (ret < 0) {
576576
dev_err(dai->dev, "Failed to clr TX_DPTH: %d\n", ret);
577577
return ret;
@@ -751,9 +751,9 @@ static int fsl_xcvr_trigger(struct snd_pcm_substream *substream, int cmd,
751751
}
752752
fallthrough;
753753
case FSL_XCVR_MODE_SPDIF:
754-
ret = regmap_write(xcvr->regmap,
755-
FSL_XCVR_TX_DPTH_CTRL_SET,
756-
FSL_XCVR_TX_DPTH_CTRL_STRT_DATA_TX);
754+
ret = regmap_set_bits(xcvr->regmap,
755+
FSL_XCVR_TX_DPTH_CTRL,
756+
FSL_XCVR_TX_DPTH_CTRL_STRT_DATA_TX);
757757
if (ret < 0) {
758758
dev_err(dai->dev, "Failed to start DATA_TX: %d\n", ret);
759759
goto release_lock;
@@ -809,9 +809,9 @@ static int fsl_xcvr_trigger(struct snd_pcm_substream *substream, int cmd,
809809
if (tx) {
810810
switch (xcvr->mode) {
811811
case FSL_XCVR_MODE_SPDIF:
812-
ret = regmap_write(xcvr->regmap,
813-
FSL_XCVR_TX_DPTH_CTRL_CLR,
814-
FSL_XCVR_TX_DPTH_CTRL_STRT_DATA_TX);
812+
ret = regmap_clear_bits(xcvr->regmap,
813+
FSL_XCVR_TX_DPTH_CTRL,
814+
FSL_XCVR_TX_DPTH_CTRL_STRT_DATA_TX);
815815
if (ret < 0) {
816816
dev_err(dai->dev, "Failed to stop DATA_TX: %d\n", ret);
817817
goto release_lock;
@@ -1224,6 +1224,7 @@ static bool fsl_xcvr_writeable_reg(struct device *dev, unsigned int reg)
12241224
case FSL_XCVR_RX_DPTH_CNTR_CTRL_SET:
12251225
case FSL_XCVR_RX_DPTH_CNTR_CTRL_CLR:
12261226
case FSL_XCVR_RX_DPTH_CNTR_CTRL_TOG:
1227+
case FSL_XCVR_TX_DPTH_CTRL:
12271228
case FSL_XCVR_TX_DPTH_CTRL_SET:
12281229
case FSL_XCVR_TX_DPTH_CTRL_CLR:
12291230
case FSL_XCVR_TX_DPTH_CTRL_TOG:
@@ -1245,7 +1246,49 @@ static bool fsl_xcvr_writeable_reg(struct device *dev, unsigned int reg)
12451246

12461247
static bool fsl_xcvr_volatile_reg(struct device *dev, unsigned int reg)
12471248
{
1248-
return fsl_xcvr_readable_reg(dev, reg);
1249+
switch (reg) {
1250+
case FSL_XCVR_EXT_STATUS:
1251+
case FSL_XCVR_EXT_ISR:
1252+
case FSL_XCVR_EXT_ISR_SET:
1253+
case FSL_XCVR_EXT_ISR_CLR:
1254+
case FSL_XCVR_EXT_ISR_TOG:
1255+
case FSL_XCVR_ISR:
1256+
case FSL_XCVR_ISR_SET:
1257+
case FSL_XCVR_ISR_CLR:
1258+
case FSL_XCVR_ISR_TOG:
1259+
case FSL_XCVR_PHY_AI_CTRL:
1260+
case FSL_XCVR_PHY_AI_CTRL_SET:
1261+
case FSL_XCVR_PHY_AI_CTRL_CLR:
1262+
case FSL_XCVR_PHY_AI_CTRL_TOG:
1263+
case FSL_XCVR_PHY_AI_RDATA:
1264+
case FSL_XCVR_RX_CS_DATA_0:
1265+
case FSL_XCVR_RX_CS_DATA_1:
1266+
case FSL_XCVR_RX_CS_DATA_2:
1267+
case FSL_XCVR_RX_CS_DATA_3:
1268+
case FSL_XCVR_RX_CS_DATA_4:
1269+
case FSL_XCVR_RX_CS_DATA_5:
1270+
case FSL_XCVR_RX_DPTH_CNTR_CTRL:
1271+
case FSL_XCVR_RX_DPTH_CNTR_CTRL_SET:
1272+
case FSL_XCVR_RX_DPTH_CNTR_CTRL_CLR:
1273+
case FSL_XCVR_RX_DPTH_CNTR_CTRL_TOG:
1274+
case FSL_XCVR_RX_DPTH_TSCR:
1275+
case FSL_XCVR_RX_DPTH_BCR:
1276+
case FSL_XCVR_RX_DPTH_BCTR:
1277+
case FSL_XCVR_RX_DPTH_BCRR:
1278+
case FSL_XCVR_TX_DPTH_CNTR_CTRL:
1279+
case FSL_XCVR_TX_DPTH_CNTR_CTRL_SET:
1280+
case FSL_XCVR_TX_DPTH_CNTR_CTRL_CLR:
1281+
case FSL_XCVR_TX_DPTH_CNTR_CTRL_TOG:
1282+
case FSL_XCVR_TX_DPTH_TSCR:
1283+
case FSL_XCVR_TX_DPTH_BCR:
1284+
case FSL_XCVR_TX_DPTH_BCTR:
1285+
case FSL_XCVR_TX_DPTH_BCRR:
1286+
case FSL_XCVR_DEBUG_REG_0:
1287+
case FSL_XCVR_DEBUG_REG_1:
1288+
return true;
1289+
default:
1290+
return false;
1291+
}
12491292
}
12501293

12511294
static const struct regmap_config fsl_xcvr_regmap_cfg = {
@@ -1586,6 +1629,10 @@ static int fsl_xcvr_probe(struct platform_device *pdev)
15861629
platform_set_drvdata(pdev, xcvr);
15871630
pm_runtime_enable(dev);
15881631
regcache_cache_only(xcvr->regmap, true);
1632+
if (xcvr->soc_data->use_phy) {
1633+
regcache_cache_only(xcvr->regmap_phy, true);
1634+
regcache_cache_only(xcvr->regmap_pll, true);
1635+
}
15891636

15901637
/*
15911638
* Register platform component before registering cpu dai for there
@@ -1624,7 +1671,8 @@ static int fsl_xcvr_runtime_suspend(struct device *dev)
16241671
struct fsl_xcvr *xcvr = dev_get_drvdata(dev);
16251672
int ret;
16261673

1627-
if (!xcvr->soc_data->spdif_only) {
1674+
if (!xcvr->soc_data->spdif_only &&
1675+
xcvr->mode == FSL_XCVR_MODE_EARC) {
16281676
/* Assert M0+ reset */
16291677
ret = regmap_update_bits(xcvr->regmap, FSL_XCVR_EXT_CTRL,
16301678
FSL_XCVR_EXT_CTRL_CORE_RESET,
@@ -1634,6 +1682,10 @@ static int fsl_xcvr_runtime_suspend(struct device *dev)
16341682
}
16351683

16361684
regcache_cache_only(xcvr->regmap, true);
1685+
if (xcvr->soc_data->use_phy) {
1686+
regcache_cache_only(xcvr->regmap_phy, true);
1687+
regcache_cache_only(xcvr->regmap_pll, true);
1688+
}
16371689

16381690
clk_disable_unprepare(xcvr->spba_clk);
16391691
clk_disable_unprepare(xcvr->phy_clk);
@@ -1678,6 +1730,12 @@ static int fsl_xcvr_runtime_resume(struct device *dev)
16781730
goto stop_phy_clk;
16791731
}
16801732

1733+
ret = reset_control_deassert(xcvr->reset);
1734+
if (ret) {
1735+
dev_err(dev, "failed to deassert M0+ reset.\n");
1736+
goto stop_spba_clk;
1737+
}
1738+
16811739
regcache_cache_only(xcvr->regmap, false);
16821740
regcache_mark_dirty(xcvr->regmap);
16831741
ret = regcache_sync(xcvr->regmap);
@@ -1687,31 +1745,49 @@ static int fsl_xcvr_runtime_resume(struct device *dev)
16871745
goto stop_spba_clk;
16881746
}
16891747

1690-
if (xcvr->soc_data->spdif_only)
1691-
return 0;
1748+
if (xcvr->soc_data->use_phy) {
1749+
ret = regmap_write(xcvr->regmap, FSL_XCVR_PHY_AI_CTRL_SET,
1750+
FSL_XCVR_PHY_AI_CTRL_AI_RESETN);
1751+
if (ret < 0) {
1752+
dev_err(dev, "Error while release PHY reset: %d\n", ret);
1753+
goto stop_spba_clk;
1754+
}
16921755

1693-
ret = reset_control_deassert(xcvr->reset);
1694-
if (ret) {
1695-
dev_err(dev, "failed to deassert M0+ reset.\n");
1696-
goto stop_spba_clk;
1697-
}
1756+
regcache_cache_only(xcvr->regmap_phy, false);
1757+
regcache_mark_dirty(xcvr->regmap_phy);
1758+
ret = regcache_sync(xcvr->regmap_phy);
1759+
if (ret) {
1760+
dev_err(dev, "failed to sync phy regcache.\n");
1761+
goto stop_spba_clk;
1762+
}
16981763

1699-
ret = fsl_xcvr_load_firmware(xcvr);
1700-
if (ret) {
1701-
dev_err(dev, "failed to load firmware.\n");
1702-
goto stop_spba_clk;
1764+
regcache_cache_only(xcvr->regmap_pll, false);
1765+
regcache_mark_dirty(xcvr->regmap_pll);
1766+
ret = regcache_sync(xcvr->regmap_pll);
1767+
if (ret) {
1768+
dev_err(dev, "failed to sync pll regcache.\n");
1769+
goto stop_spba_clk;
1770+
}
17031771
}
17041772

1705-
/* Release M0+ reset */
1706-
ret = regmap_update_bits(xcvr->regmap, FSL_XCVR_EXT_CTRL,
1707-
FSL_XCVR_EXT_CTRL_CORE_RESET, 0);
1708-
if (ret < 0) {
1709-
dev_err(dev, "M0+ core release failed: %d\n", ret);
1710-
goto stop_spba_clk;
1711-
}
1773+
if (xcvr->mode == FSL_XCVR_MODE_EARC) {
1774+
ret = fsl_xcvr_load_firmware(xcvr);
1775+
if (ret) {
1776+
dev_err(dev, "failed to load firmware.\n");
1777+
goto stop_spba_clk;
1778+
}
17121779

1713-
/* Let M0+ core complete firmware initialization */
1714-
msleep(50);
1780+
/* Release M0+ reset */
1781+
ret = regmap_update_bits(xcvr->regmap, FSL_XCVR_EXT_CTRL,
1782+
FSL_XCVR_EXT_CTRL_CORE_RESET, 0);
1783+
if (ret < 0) {
1784+
dev_err(dev, "M0+ core release failed: %d\n", ret);
1785+
goto stop_spba_clk;
1786+
}
1787+
1788+
/* Let M0+ core complete firmware initialization */
1789+
msleep(50);
1790+
}
17151791

17161792
return 0;
17171793

0 commit comments

Comments
 (0)