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..b75843e31f00 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 = 0, *npll = 0; +	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 %s: %d\n", __clk_get_name(npll), 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"); | 
