FROMLIST: ASoC: rockchip: implement system suspend/resume for spdif
[firefly-linux-kernel-4.4.55.git] / sound / soc / rockchip / rockchip_spdif.c
index ac72ff5055bbce626550c4fd277a96c351321b25..2329c8a60cbfcdd1aad598b4abf71a01289d05a4 100644 (file)
@@ -28,6 +28,7 @@ enum rk_spdif_type {
        RK_SPDIF_RK3066,
        RK_SPDIF_RK3188,
        RK_SPDIF_RK3288,
+       RK_SPDIF_RK3366,
 };
 
 #define RK3288_GRF_SOC_CON2 0x24c
@@ -45,11 +46,17 @@ struct rk_spdif_dev {
 
 static const struct of_device_id rk_spdif_match[] = {
        { .compatible = "rockchip,rk3066-spdif",
-         .data = (void *) RK_SPDIF_RK3066 },
+         .data = (void *)RK_SPDIF_RK3066 },
        { .compatible = "rockchip,rk3188-spdif",
-         .data = (void *) RK_SPDIF_RK3188 },
+         .data = (void *)RK_SPDIF_RK3188 },
        { .compatible = "rockchip,rk3288-spdif",
-         .data = (void *) RK_SPDIF_RK3288 },
+         .data = (void *)RK_SPDIF_RK3288 },
+       { .compatible = "rockchip,rk3366-spdif",
+         .data = (void *)RK_SPDIF_RK3366 },
+       { .compatible = "rockchip,rk3368-spdif",
+         .data = (void *)RK_SPDIF_RK3366 },
+       { .compatible = "rockchip,rk3399-spdif",
+         .data = (void *)RK_SPDIF_RK3366 },
        {},
 };
 MODULE_DEVICE_TABLE(of, rk_spdif_match);
@@ -152,8 +159,10 @@ static int rk_spdif_trigger(struct snd_pcm_substream *substream,
        case SNDRV_PCM_TRIGGER_RESUME:
        case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
                ret = regmap_update_bits(spdif->regmap, SPDIF_DMACR,
-                                  SPDIF_DMACR_TDE_ENABLE,
-                                  SPDIF_DMACR_TDE_ENABLE);
+                                  SPDIF_DMACR_TDE_ENABLE |
+                                  SPDIF_DMACR_TDL_MASK,
+                                  SPDIF_DMACR_TDE_ENABLE |
+                                  SPDIF_DMACR_TDL(16));
 
                if (ret != 0)
                        return ret;
@@ -383,9 +392,35 @@ static int rk_spdif_remove(struct platform_device *pdev)
        return 0;
 }
 
+#ifdef CONFIG_PM_SLEEP
+static int rockchip_spdif_suspend(struct device *dev)
+{
+       struct rk_spdif_dev *spdif = dev_get_drvdata(dev);
+
+       regcache_mark_dirty(spdif->regmap);
+
+       return 0;
+}
+
+static int rockchip_spdif_resume(struct device *dev)
+{
+       struct rk_spdif_dev *spdif = dev_get_drvdata(dev);
+       int ret;
+
+       ret = pm_runtime_get_sync(dev);
+       if (ret < 0)
+               return ret;
+       ret = regcache_sync(spdif->regmap);
+       pm_runtime_put(dev);
+
+       return ret;
+}
+#endif
+
 static const struct dev_pm_ops rk_spdif_pm_ops = {
        SET_RUNTIME_PM_OPS(rk_spdif_runtime_suspend, rk_spdif_runtime_resume,
                           NULL)
+       SET_SYSTEM_SLEEP_PM_OPS(rockchip_spdif_suspend, rockchip_spdif_resume)
 };
 
 static struct platform_driver rk_spdif_driver = {