ASoC: tegra-alt: Add dmic clock support
Manoj Gangwal [Tue, 19 May 2015 06:20:25 +0000 (11:20 +0530)]
Add support for configuring dmic clock.

Bug 200078772

Change-Id: I9196d78c2e1fd1c8dfc5fe4f0163fe7561cfa318
Signed-off-by: Manoj Gangwal <mgangwal@nvidia.com>
Reviewed-on: http://git-master/r/744166
(cherry picked from commit 2f648f477bbbd827d0a08a6ec524d1e6ac45dd40)
Reviewed-on: http://git-master/r/748217
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Ravindra Lokhande <rlokhande@nvidia.com>
Reviewed-by: Sanjay Singh Chauhan <schauhan@nvidia.com>
GVS: Gerrit_Virtual_Submit
Reviewed-by: Sumit Bhattacharya <sumitb@nvidia.com>

sound/soc/tegra-alt/tegra210_dmic_alt.c
sound/soc/tegra-alt/tegra210_dmic_alt.h

index 647754c..6fc2af0 100644 (file)
@@ -31,7 +31,6 @@
 #include <linux/of_device.h>
 #include <linux/debugfs.h>
 #include <linux/pinctrl/pinconf-tegra.h>
-
 #include "tegra210_xbar_alt.h"
 #include "tegra210_dmic_alt.h"
 #include "ahub_unit_fpga_clock.h"
@@ -122,12 +121,18 @@ static int tegra210_dmic_hw_params(struct snd_pcm_substream *substream,
 {
        struct device *dev = dai->dev;
        struct tegra210_dmic *dmic = snd_soc_dai_get_drvdata(dai);
-       int channels, srate, dmic_clk, osr = TEGRA210_DMIC_OSR_64;
+       int channels, srate, dmic_clk, osr = TEGRA210_DMIC_OSR_64, ret;
        struct tegra210_xbar_cif_conf cif_conf;
 
        channels = params_channels(params);
        srate = params_rate(params);
-       dmic_clk = (1 << (6+osr)) * (srate/2);
+       dmic_clk = (1 << (6+osr)) * (srate);
+
+       ret = clk_set_rate(dmic->clk_dmic, dmic_clk);
+       if (ret) {
+               dev_err(dev, "Can't set dmic clock rate: %d\n", ret);
+               return ret;
+       }
 
 #ifdef CONFIG_MACH_GRENADA
        program_dmic_gpio();
@@ -371,11 +376,24 @@ static int tegra210_dmic_platform_probe(struct platform_device *pdev)
                goto err;
        }
 
+       dmic->clk_pll_a_out0 = clk_get_sys(NULL, "pll_a_out0");
+       if (IS_ERR_OR_NULL(dmic->clk_pll_a_out0)) {
+               dev_err(&pdev->dev, "Can't retrieve pll_a_out0 clock\n");
+               ret = -ENOENT;
+               goto err_clk_put;
+       }
+
+       ret = clk_set_parent(dmic->clk_dmic, dmic->clk_pll_a_out0);
+       if (ret) {
+               dev_err(&pdev->dev, "Can't set parent of dmic clock\n");
+               goto err_plla_clk_put;
+       }
+
        mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!mem) {
                dev_err(&pdev->dev, "No memory resource\n");
                ret = -ENODEV;
-               goto err_clk_put;
+               goto err_plla_clk_put;
        }
 
        memregion = devm_request_mem_region(&pdev->dev, mem->start,
@@ -383,14 +401,14 @@ static int tegra210_dmic_platform_probe(struct platform_device *pdev)
        if (!memregion) {
                dev_err(&pdev->dev, "Memory region already claimed\n");
                ret = -EBUSY;
-               goto err_clk_put;
+               goto err_plla_clk_put;
        }
 
        regs = devm_ioremap(&pdev->dev, mem->start, resource_size(mem));
        if (!regs) {
                dev_err(&pdev->dev, "ioremap failed\n");
                ret = -ENOMEM;
-               goto err_clk_put;
+               goto err_plla_clk_put;
        }
 
        dmic->regmap = devm_regmap_init_mmio(&pdev->dev, regs,
@@ -398,7 +416,7 @@ static int tegra210_dmic_platform_probe(struct platform_device *pdev)
        if (IS_ERR(dmic->regmap)) {
                dev_err(&pdev->dev, "regmap init failed\n");
                ret = PTR_ERR(dmic->regmap);
-               goto err_clk_put;
+               goto err_plla_clk_put;
        }
        regcache_cache_only(dmic->regmap, true);
 
@@ -407,7 +425,7 @@ static int tegra210_dmic_platform_probe(struct platform_device *pdev)
                dev_err(&pdev->dev,
                        "Missing property nvidia,ahub-dmic-id\n");
                ret = -ENODEV;
-               goto err_clk_put;
+               goto err_plla_clk_put;
        }
 
        pm_runtime_enable(&pdev->dev);
@@ -435,6 +453,8 @@ err_suspend:
                tegra210_dmic_runtime_suspend(&pdev->dev);
 err_pm_disable:
        pm_runtime_disable(&pdev->dev);
+err_plla_clk_put:
+       devm_clk_put(&pdev->dev, dmic->clk_pll_a_out0);
 err_clk_put:
        devm_clk_put(&pdev->dev, dmic->clk_dmic);
 err:
@@ -452,6 +472,7 @@ static int tegra210_dmic_platform_remove(struct platform_device *pdev)
        if (!pm_runtime_status_suspended(&pdev->dev))
                tegra210_dmic_runtime_suspend(&pdev->dev);
 
+       devm_clk_put(&pdev->dev, dmic->clk_pll_a_out0);
        devm_clk_put(&pdev->dev, dmic->clk_dmic);
        return 0;
 }
index 0be63c0..d04c99e 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * tegra210_dmic_alt.h - Definitions for Tegra210 DMIC driver
  *
- * Copyright (c) 2014 NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2014-2015 NVIDIA CORPORATION.  All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
@@ -116,6 +116,7 @@ struct tegra210_dmic_soc_data {
 
 struct tegra210_dmic {
        struct clk *clk_dmic;
+       struct clk *clk_pll_a_out0;
        struct regmap *regmap;
        const struct tegra210_dmic_soc_data *soc_data;
 };