summaryrefslogtreecommitdiff
path: root/sound/soc/fsl
diff options
context:
space:
mode:
authorShengjiu Wang <shengjiu.wang@nxp.com>2020-03-17 18:26:44 +0800
committerShengjiu Wang <shengjiu.wang@nxp.com>2020-03-18 15:41:46 +0800
commitee1a47b87fff88e7cb97bc6dce0a8a7fafbd38bc (patch)
tree6ea79f9796cd998456bda52f6a69e5c88709d18b /sound/soc/fsl
parentc43a9a158c43e55151c9d4e17ce2e38d40e1fa44 (diff)
MLK-23618-6: ASoC: fsl_dsp: refine handling of multi power domain
The attached multi power domain is enabled by device_link_add So we need to disable them in probe, otherwise it may impact the power consumption. Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com> Reviewed-by: Daniel Baluta <daniel.baluta@nxp.com>
Diffstat (limited to 'sound/soc/fsl')
-rw-r--r--sound/soc/fsl/fsl_dsp.c116
-rw-r--r--sound/soc/fsl/fsl_dsp.h3
2 files changed, 99 insertions, 20 deletions
diff --git a/sound/soc/fsl/fsl_dsp.c b/sound/soc/fsl/fsl_dsp.c
index 4cf051449f21..1776ee75f153 100644
--- a/sound/soc/fsl/fsl_dsp.c
+++ b/sound/soc/fsl/fsl_dsp.c
@@ -877,6 +877,93 @@ int fsl_dsp_configure(struct fsl_dsp *dsp_priv)
}
}
+/**
+ * fsl_dsp_attach_pm_domains
+ */
+static int fsl_dsp_attach_pm_domains(struct device *dev,
+ struct fsl_dsp *dsp)
+{
+ int ret;
+ int i;
+
+ if (dsp->num_domains <= 1)
+ return 0;
+
+ dsp->pd_dev = devm_kmalloc_array(dev, dsp->num_domains,
+ sizeof(*dsp->pd_dev),
+ GFP_KERNEL);
+ if (!dsp->pd_dev)
+ return -ENOMEM;
+
+ dsp->pd_dev_link = devm_kmalloc_array(dev,
+ dsp->num_domains,
+ sizeof(*dsp->pd_dev_link),
+ GFP_KERNEL);
+ if (!dsp->pd_dev_link)
+ return -ENOMEM;
+
+ for (i = 0; i < dsp->num_domains; i++) {
+ dsp->pd_dev[i] = dev_pm_domain_attach_by_id(dev, i);
+ if (IS_ERR(dsp->pd_dev[i]))
+ return PTR_ERR(dsp->pd_dev[i]);
+
+ dsp->pd_dev_link[i] = device_link_add(dev,
+ dsp->pd_dev[i],
+ DL_FLAG_STATELESS |
+ DL_FLAG_PM_RUNTIME |
+ DL_FLAG_RPM_ACTIVE);
+ if (IS_ERR(dsp->pd_dev_link[i])) {
+ dev_pm_domain_detach(dsp->pd_dev[i], false);
+ ret = PTR_ERR(dsp->pd_dev_link[i]);
+ goto detach_pm;
+ }
+ }
+ return 0;
+
+detach_pm:
+ while (--i >= 0) {
+ device_link_del(dsp->pd_dev_link[i]);
+ dev_pm_domain_detach(dsp->pd_dev[i], false);
+ }
+ return ret;
+}
+
+/**
+ * fsl_dsp_detach_pm_domains
+ */
+static int fsl_dsp_detach_pm_domains(struct device *dev,
+ struct fsl_dsp *dsp)
+{
+ int i;
+
+ if (dsp->num_domains <= 1)
+ return 0;
+
+ for (i = 0; i < dsp->num_domains; i++) {
+ device_link_del(dsp->pd_dev_link[i]);
+ dev_pm_domain_detach(dsp->pd_dev[i], false);
+ }
+
+ return 0;
+}
+
+/**
+ * fsl_dev_put_pm_domains
+ */
+static int fsl_dsp_put_pm_domains(struct device *dev,
+ struct fsl_dsp *dsp)
+{
+ int i;
+
+ if (dsp->num_domains <= 1)
+ return 0;
+
+ for (i = 0; i < dsp->num_domains; i++)
+ pm_runtime_put_sync(dsp->pd_dev[i]);
+
+ return 0;
+}
+
static int fsl_dsp_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
@@ -890,7 +977,6 @@ static int fsl_dsp_probe(struct platform_device *pdev)
dma_addr_t buf_phys;
int size, offset, i;
int ret;
- int num_domains = 0;
char tmp[16];
dsp_priv = devm_kzalloc(&pdev->dev, sizeof(*dsp_priv), GFP_KERNEL);
@@ -920,25 +1006,11 @@ static int fsl_dsp_probe(struct platform_device *pdev)
dsp_priv->iram = dsp_priv->paddr + IRAM_OFFSET;
dsp_priv->sram = dsp_priv->paddr + SYSRAM_OFFSET;
- num_domains = of_count_phandle_with_args(np, "power-domains",
- "#power-domain-cells");
- if (num_domains > 1) {
- for (i = 0; i < num_domains; i++) {
- struct device *pd_dev;
- struct device_link *link;
-
- pd_dev = dev_pm_domain_attach_by_id(&pdev->dev, i);
- if (IS_ERR(pd_dev))
- return PTR_ERR(pd_dev);
-
- link = device_link_add(&pdev->dev, pd_dev,
- DL_FLAG_STATELESS |
- DL_FLAG_PM_RUNTIME |
- DL_FLAG_RPM_ACTIVE);
- if (IS_ERR(link))
- return PTR_ERR(link);
- }
- }
+ dsp_priv->num_domains = of_count_phandle_with_args(np, "power-domains",
+ "#power-domain-cells");
+ ret = fsl_dsp_attach_pm_domains(&pdev->dev, dsp_priv);
+ if (ret)
+ return ret;
ret = fsl_dsp_configure(dsp_priv);
if (ret < 0)
@@ -955,6 +1027,7 @@ static int fsl_dsp_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, dsp_priv);
pm_runtime_enable(&pdev->dev);
+ fsl_dsp_put_pm_domains(&pdev->dev, dsp_priv);
dsp_miscdev.fops = &dsp_fops,
dsp_miscdev.parent = &pdev->dev,
@@ -1099,6 +1172,9 @@ static int fsl_dsp_remove(struct platform_device *pdev)
if (dsp_priv->sdram_vir_addr)
iounmap(dsp_priv->sdram_vir_addr);
+ pm_runtime_disable(&pdev->dev);
+ fsl_dsp_detach_pm_domains(&pdev->dev, dsp_priv);
+
return 0;
}
diff --git a/sound/soc/fsl/fsl_dsp.h b/sound/soc/fsl/fsl_dsp.h
index c731cd9a0e94..d074cc8008db 100644
--- a/sound/soc/fsl/fsl_dsp.h
+++ b/sound/soc/fsl/fsl_dsp.h
@@ -117,6 +117,9 @@ struct fsl_dsp {
struct clk *dsp_root_clk;
struct clk *debug_clk;
struct clk *mu2_clk;
+ struct device **pd_dev;
+ struct device_link **pd_dev_link;
+ int num_domains;
};
#define IRAM_OFFSET 0x10000