|
@@ -108,6 +108,8 @@ struct fsl_spdif_priv {
|
|
|
struct clk *sysclk;
|
|
|
struct snd_dmaengine_dai_dma_data dma_params_tx;
|
|
|
struct snd_dmaengine_dai_dma_data dma_params_rx;
|
|
|
+ /* regcache for SRPC */
|
|
|
+ u32 regcache_srpc;
|
|
|
};
|
|
|
|
|
|
/* DPLL locked and lock loss interrupt handler */
|
|
@@ -300,6 +302,8 @@ static int spdif_softreset(struct fsl_spdif_priv *spdif_priv)
|
|
|
struct regmap *regmap = spdif_priv->regmap;
|
|
|
u32 val, cycle = 1000;
|
|
|
|
|
|
+ regcache_cache_bypass(regmap, true);
|
|
|
+
|
|
|
regmap_write(regmap, REG_SPDIF_SCR, SCR_SOFT_RESET);
|
|
|
|
|
|
/*
|
|
@@ -310,6 +314,10 @@ static int spdif_softreset(struct fsl_spdif_priv *spdif_priv)
|
|
|
regmap_read(regmap, REG_SPDIF_SCR, &val);
|
|
|
} while ((val & SCR_SOFT_RESET) && cycle--);
|
|
|
|
|
|
+ regcache_cache_bypass(regmap, false);
|
|
|
+ regcache_mark_dirty(regmap);
|
|
|
+ regcache_sync(regmap);
|
|
|
+
|
|
|
if (cycle)
|
|
|
return 0;
|
|
|
else
|
|
@@ -997,6 +1005,14 @@ static const struct snd_soc_component_driver fsl_spdif_component = {
|
|
|
};
|
|
|
|
|
|
/* FSL SPDIF REGMAP */
|
|
|
+static const struct reg_default fsl_spdif_reg_defaults[] = {
|
|
|
+ {0x0, 0x00000400},
|
|
|
+ {0x4, 0x00000000},
|
|
|
+ {0xc, 0x00000000},
|
|
|
+ {0x34, 0x00000000},
|
|
|
+ {0x38, 0x00000000},
|
|
|
+ {0x50, 0x00020f00},
|
|
|
+};
|
|
|
|
|
|
static bool fsl_spdif_readable_reg(struct device *dev, unsigned int reg)
|
|
|
{
|
|
@@ -1022,6 +1038,26 @@ static bool fsl_spdif_readable_reg(struct device *dev, unsigned int reg)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+static bool fsl_spdif_volatile_reg(struct device *dev, unsigned int reg)
|
|
|
+{
|
|
|
+ switch (reg) {
|
|
|
+ case REG_SPDIF_SRPC:
|
|
|
+ case REG_SPDIF_SIS:
|
|
|
+ case REG_SPDIF_SRL:
|
|
|
+ case REG_SPDIF_SRR:
|
|
|
+ case REG_SPDIF_SRCSH:
|
|
|
+ case REG_SPDIF_SRCSL:
|
|
|
+ case REG_SPDIF_SRU:
|
|
|
+ case REG_SPDIF_SRQ:
|
|
|
+ case REG_SPDIF_STL:
|
|
|
+ case REG_SPDIF_STR:
|
|
|
+ case REG_SPDIF_SRFM:
|
|
|
+ return true;
|
|
|
+ default:
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
static bool fsl_spdif_writeable_reg(struct device *dev, unsigned int reg)
|
|
|
{
|
|
|
switch (reg) {
|
|
@@ -1047,8 +1083,12 @@ static const struct regmap_config fsl_spdif_regmap_config = {
|
|
|
.val_bits = 32,
|
|
|
|
|
|
.max_register = REG_SPDIF_STC,
|
|
|
+ .reg_defaults = fsl_spdif_reg_defaults,
|
|
|
+ .num_reg_defaults = ARRAY_SIZE(fsl_spdif_reg_defaults),
|
|
|
.readable_reg = fsl_spdif_readable_reg,
|
|
|
+ .volatile_reg = fsl_spdif_volatile_reg,
|
|
|
.writeable_reg = fsl_spdif_writeable_reg,
|
|
|
+ .cache_type = REGCACHE_RBTREE,
|
|
|
};
|
|
|
|
|
|
static u32 fsl_spdif_txclk_caldiv(struct fsl_spdif_priv *spdif_priv,
|
|
@@ -1271,6 +1311,38 @@ static int fsl_spdif_probe(struct platform_device *pdev)
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
+#ifdef CONFIG_PM_SLEEP
|
|
|
+static int fsl_spdif_suspend(struct device *dev)
|
|
|
+{
|
|
|
+ struct fsl_spdif_priv *spdif_priv = dev_get_drvdata(dev);
|
|
|
+
|
|
|
+ regmap_read(spdif_priv->regmap, REG_SPDIF_SRPC,
|
|
|
+ &spdif_priv->regcache_srpc);
|
|
|
+
|
|
|
+ regcache_cache_only(spdif_priv->regmap, true);
|
|
|
+ regcache_mark_dirty(spdif_priv->regmap);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int fsl_spdif_resume(struct device *dev)
|
|
|
+{
|
|
|
+ struct fsl_spdif_priv *spdif_priv = dev_get_drvdata(dev);
|
|
|
+
|
|
|
+ regcache_cache_only(spdif_priv->regmap, false);
|
|
|
+
|
|
|
+ regmap_update_bits(spdif_priv->regmap, REG_SPDIF_SRPC,
|
|
|
+ SRPC_CLKSRC_SEL_MASK | SRPC_GAINSEL_MASK,
|
|
|
+ spdif_priv->regcache_srpc);
|
|
|
+
|
|
|
+ return regcache_sync(spdif_priv->regmap);
|
|
|
+}
|
|
|
+#endif /* CONFIG_PM_SLEEP */
|
|
|
+
|
|
|
+static const struct dev_pm_ops fsl_spdif_pm = {
|
|
|
+ SET_SYSTEM_SLEEP_PM_OPS(fsl_spdif_suspend, fsl_spdif_resume)
|
|
|
+};
|
|
|
+
|
|
|
static const struct of_device_id fsl_spdif_dt_ids[] = {
|
|
|
{ .compatible = "fsl,imx35-spdif", },
|
|
|
{ .compatible = "fsl,vf610-spdif", },
|
|
@@ -1282,6 +1354,7 @@ static struct platform_driver fsl_spdif_driver = {
|
|
|
.driver = {
|
|
|
.name = "fsl-spdif-dai",
|
|
|
.of_match_table = fsl_spdif_dt_ids,
|
|
|
+ .pm = &fsl_spdif_pm,
|
|
|
},
|
|
|
.probe = fsl_spdif_probe,
|
|
|
};
|