diff options
Diffstat (limited to 'sound/soc/fsl/fsl_utils.c')
-rw-r--r-- | sound/soc/fsl/fsl_utils.c | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/sound/soc/fsl/fsl_utils.c b/sound/soc/fsl/fsl_utils.c index 9bab202569af..d0fc430f7033 100644 --- a/sound/soc/fsl/fsl_utils.c +++ b/sound/soc/fsl/fsl_utils.c @@ -6,6 +6,8 @@ // // Copyright 2010 Freescale Semiconductor, Inc. +#include <linux/clk.h> +#include <linux/clk-provider.h> #include <linux/module.h> #include <linux/of_address.h> #include <sound/soc.h> @@ -83,6 +85,73 @@ int fsl_asoc_get_dma_channel(struct device_node *ssi_np, } EXPORT_SYMBOL(fsl_asoc_get_dma_channel); +/** + * fsl_asoc_get_pll_clocks - get two PLL clock source + * + * @dev: device pointer + * @pll8k_clk: PLL clock pointer for 8kHz + * @pll11k_clk: PLL clock pointer for 11kHz + * + * This function get two PLL clock source + */ +void fsl_asoc_get_pll_clocks(struct device *dev, struct clk **pll8k_clk, + struct clk **pll11k_clk) +{ + *pll8k_clk = devm_clk_get(dev, "pll8k"); + if (IS_ERR(*pll8k_clk)) + *pll8k_clk = NULL; + + *pll11k_clk = devm_clk_get(dev, "pll11k"); + if (IS_ERR(*pll11k_clk)) + *pll11k_clk = NULL; +} +EXPORT_SYMBOL(fsl_asoc_get_pll_clocks); + +/** + * fsl_asoc_reparent_pll_clocks - set clock parent if necessary + * + * @dev: device pointer + * @clk: root clock pointer + * @pll8k_clk: PLL clock pointer for 8kHz + * @pll11k_clk: PLL clock pointer for 11kHz + * @ratio: target requency for root clock + * + * This function set root clock parent according to the target ratio + */ +void fsl_asoc_reparent_pll_clocks(struct device *dev, struct clk *clk, + struct clk *pll8k_clk, + struct clk *pll11k_clk, u64 ratio) +{ + struct clk *p, *pll = NULL, *npll = NULL; + bool reparent = false; + int ret = 0; + + if (!clk || !pll8k_clk || !pll11k_clk) + return; + + p = clk; + while (p && pll8k_clk && pll11k_clk) { + struct clk *pp = clk_get_parent(p); + + if (clk_is_match(pp, pll8k_clk) || + clk_is_match(pp, pll11k_clk)) { + pll = pp; + break; + } + p = pp; + } + + npll = (do_div(ratio, 8000) ? pll11k_clk : pll8k_clk); + reparent = (pll && !clk_is_match(pll, npll)); + + if (reparent) { + ret = clk_set_parent(p, npll); + if (ret < 0) + dev_warn(dev, "failed to set parent:%d\n", ret); + } +} +EXPORT_SYMBOL(fsl_asoc_reparent_pll_clocks); + MODULE_AUTHOR("Timur Tabi <timur@freescale.com>"); MODULE_DESCRIPTION("Freescale ASoC utility code"); MODULE_LICENSE("GPL v2"); |