aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/fsl
diff options
context:
space:
mode:
authorZidan Wang <zidan.wang@freescale.com>2015-09-17 23:09:11 -0400
committerMark Brown <broonie@kernel.org>2015-10-05 12:26:17 -0400
commitf9f4fa61aab9417e40898cf6706fffa94005dc44 (patch)
tree2542308c1e3b9b55482e98cb677ee09843cfedd7 /sound/soc/fsl
parent1fde5e83a17acbcfcce27f68be46a6da4344efbd (diff)
ASoC: fsl_spdif: Add driver suspend and resume to support MEGA Fast
For i.MX6 SoloX, there is a mode of the SoC to shutdown all power source of modules during system suspend and resume procedure. Thus, SPDIF needs to save all the values of registers before the system suspend and restore them after the system resume. The SRPC register should be volatile, LOCK bit is set by the hardware. Signed-off-by: Zidan Wang <zidan.wang@freescale.com> Acked-by: Nicolin Chen <nicoleotsuka@gmail.com> Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'sound/soc/fsl')
-rw-r--r--sound/soc/fsl/fsl_spdif.c73
1 files changed, 73 insertions, 0 deletions
diff --git a/sound/soc/fsl/fsl_spdif.c b/sound/soc/fsl/fsl_spdif.c
index ab729f2426fe..3d59bb6719f2 100644
--- a/sound/soc/fsl/fsl_spdif.c
+++ b/sound/soc/fsl/fsl_spdif.c
@@ -108,6 +108,8 @@ struct fsl_spdif_priv {
108 struct clk *sysclk; 108 struct clk *sysclk;
109 struct snd_dmaengine_dai_dma_data dma_params_tx; 109 struct snd_dmaengine_dai_dma_data dma_params_tx;
110 struct snd_dmaengine_dai_dma_data dma_params_rx; 110 struct snd_dmaengine_dai_dma_data dma_params_rx;
111 /* regcache for SRPC */
112 u32 regcache_srpc;
111}; 113};
112 114
113/* DPLL locked and lock loss interrupt handler */ 115/* DPLL locked and lock loss interrupt handler */
@@ -300,6 +302,8 @@ static int spdif_softreset(struct fsl_spdif_priv *spdif_priv)
300 struct regmap *regmap = spdif_priv->regmap; 302 struct regmap *regmap = spdif_priv->regmap;
301 u32 val, cycle = 1000; 303 u32 val, cycle = 1000;
302 304
305 regcache_cache_bypass(regmap, true);
306
303 regmap_write(regmap, REG_SPDIF_SCR, SCR_SOFT_RESET); 307 regmap_write(regmap, REG_SPDIF_SCR, SCR_SOFT_RESET);
304 308
305 /* 309 /*
@@ -310,6 +314,10 @@ static int spdif_softreset(struct fsl_spdif_priv *spdif_priv)
310 regmap_read(regmap, REG_SPDIF_SCR, &val); 314 regmap_read(regmap, REG_SPDIF_SCR, &val);
311 } while ((val & SCR_SOFT_RESET) && cycle--); 315 } while ((val & SCR_SOFT_RESET) && cycle--);
312 316
317 regcache_cache_bypass(regmap, false);
318 regcache_mark_dirty(regmap);
319 regcache_sync(regmap);
320
313 if (cycle) 321 if (cycle)
314 return 0; 322 return 0;
315 else 323 else
@@ -997,6 +1005,14 @@ static const struct snd_soc_component_driver fsl_spdif_component = {
997}; 1005};
998 1006
999/* FSL SPDIF REGMAP */ 1007/* FSL SPDIF REGMAP */
1008static const struct reg_default fsl_spdif_reg_defaults[] = {
1009 {0x0, 0x00000400},
1010 {0x4, 0x00000000},
1011 {0xc, 0x00000000},
1012 {0x34, 0x00000000},
1013 {0x38, 0x00000000},
1014 {0x50, 0x00020f00},
1015};
1000 1016
1001static bool fsl_spdif_readable_reg(struct device *dev, unsigned int reg) 1017static bool fsl_spdif_readable_reg(struct device *dev, unsigned int reg)
1002{ 1018{
@@ -1022,6 +1038,26 @@ static bool fsl_spdif_readable_reg(struct device *dev, unsigned int reg)
1022 } 1038 }
1023} 1039}
1024 1040
1041static bool fsl_spdif_volatile_reg(struct device *dev, unsigned int reg)
1042{
1043 switch (reg) {
1044 case REG_SPDIF_SRPC:
1045 case REG_SPDIF_SIS:
1046 case REG_SPDIF_SRL:
1047 case REG_SPDIF_SRR:
1048 case REG_SPDIF_SRCSH:
1049 case REG_SPDIF_SRCSL:
1050 case REG_SPDIF_SRU:
1051 case REG_SPDIF_SRQ:
1052 case REG_SPDIF_STL:
1053 case REG_SPDIF_STR:
1054 case REG_SPDIF_SRFM:
1055 return true;
1056 default:
1057 return false;
1058 }
1059}
1060
1025static bool fsl_spdif_writeable_reg(struct device *dev, unsigned int reg) 1061static bool fsl_spdif_writeable_reg(struct device *dev, unsigned int reg)
1026{ 1062{
1027 switch (reg) { 1063 switch (reg) {
@@ -1047,8 +1083,12 @@ static const struct regmap_config fsl_spdif_regmap_config = {
1047 .val_bits = 32, 1083 .val_bits = 32,
1048 1084
1049 .max_register = REG_SPDIF_STC, 1085 .max_register = REG_SPDIF_STC,
1086 .reg_defaults = fsl_spdif_reg_defaults,
1087 .num_reg_defaults = ARRAY_SIZE(fsl_spdif_reg_defaults),
1050 .readable_reg = fsl_spdif_readable_reg, 1088 .readable_reg = fsl_spdif_readable_reg,
1089 .volatile_reg = fsl_spdif_volatile_reg,
1051 .writeable_reg = fsl_spdif_writeable_reg, 1090 .writeable_reg = fsl_spdif_writeable_reg,
1091 .cache_type = REGCACHE_RBTREE,
1052}; 1092};
1053 1093
1054static u32 fsl_spdif_txclk_caldiv(struct fsl_spdif_priv *spdif_priv, 1094static u32 fsl_spdif_txclk_caldiv(struct fsl_spdif_priv *spdif_priv,
@@ -1271,6 +1311,38 @@ static int fsl_spdif_probe(struct platform_device *pdev)
1271 return ret; 1311 return ret;
1272} 1312}
1273 1313
1314#ifdef CONFIG_PM_SLEEP
1315static int fsl_spdif_suspend(struct device *dev)
1316{
1317 struct fsl_spdif_priv *spdif_priv = dev_get_drvdata(dev);
1318
1319 regmap_read(spdif_priv->regmap, REG_SPDIF_SRPC,
1320 &spdif_priv->regcache_srpc);
1321
1322 regcache_cache_only(spdif_priv->regmap, true);
1323 regcache_mark_dirty(spdif_priv->regmap);
1324
1325 return 0;
1326}
1327
1328static int fsl_spdif_resume(struct device *dev)
1329{
1330 struct fsl_spdif_priv *spdif_priv = dev_get_drvdata(dev);
1331
1332 regcache_cache_only(spdif_priv->regmap, false);
1333
1334 regmap_update_bits(spdif_priv->regmap, REG_SPDIF_SRPC,
1335 SRPC_CLKSRC_SEL_MASK | SRPC_GAINSEL_MASK,
1336 spdif_priv->regcache_srpc);
1337
1338 return regcache_sync(spdif_priv->regmap);
1339}
1340#endif /* CONFIG_PM_SLEEP */
1341
1342static const struct dev_pm_ops fsl_spdif_pm = {
1343 SET_SYSTEM_SLEEP_PM_OPS(fsl_spdif_suspend, fsl_spdif_resume)
1344};
1345
1274static const struct of_device_id fsl_spdif_dt_ids[] = { 1346static const struct of_device_id fsl_spdif_dt_ids[] = {
1275 { .compatible = "fsl,imx35-spdif", }, 1347 { .compatible = "fsl,imx35-spdif", },
1276 { .compatible = "fsl,vf610-spdif", }, 1348 { .compatible = "fsl,vf610-spdif", },
@@ -1282,6 +1354,7 @@ static struct platform_driver fsl_spdif_driver = {
1282 .driver = { 1354 .driver = {
1283 .name = "fsl-spdif-dai", 1355 .name = "fsl-spdif-dai",
1284 .of_match_table = fsl_spdif_dt_ids, 1356 .of_match_table = fsl_spdif_dt_ids,
1357 .pm = &fsl_spdif_pm,
1285 }, 1358 },
1286 .probe = fsl_spdif_probe, 1359 .probe = fsl_spdif_probe,
1287}; 1360};