~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/sound/soc/fsl/fsl_utils.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0
  2 //
  3 // Freescale ALSA SoC Machine driver utility
  4 //
  5 // Author: Timur Tabi <timur@freescale.com>
  6 //
  7 // Copyright 2010 Freescale Semiconductor, Inc.
  8 
  9 #include <linux/clk.h>
 10 #include <linux/clk-provider.h>
 11 #include <linux/module.h>
 12 #include <linux/of_address.h>
 13 #include <sound/soc.h>
 14 
 15 #include "fsl_utils.h"
 16 
 17 /**
 18  * fsl_asoc_get_dma_channel - determine the dma channel for a SSI node
 19  *
 20  * @ssi_np: pointer to the SSI device tree node
 21  * @name: name of the phandle pointing to the dma channel
 22  * @dai: ASoC DAI link pointer to be filled with platform_name
 23  * @dma_channel_id: dma channel id to be returned
 24  * @dma_id: dma id to be returned
 25  *
 26  * This function determines the dma and channel id for given SSI node.  It
 27  * also discovers the platform_name for the ASoC DAI link.
 28  */
 29 int fsl_asoc_get_dma_channel(struct device_node *ssi_np,
 30                              const char *name,
 31                              struct snd_soc_dai_link *dai,
 32                              unsigned int *dma_channel_id,
 33                              unsigned int *dma_id)
 34 {
 35         struct resource res;
 36         struct device_node *dma_channel_np, *dma_np;
 37         const __be32 *iprop;
 38         int ret;
 39 
 40         dma_channel_np = of_parse_phandle(ssi_np, name, 0);
 41         if (!dma_channel_np)
 42                 return -EINVAL;
 43 
 44         if (!of_device_is_compatible(dma_channel_np, "fsl,ssi-dma-channel")) {
 45                 of_node_put(dma_channel_np);
 46                 return -EINVAL;
 47         }
 48 
 49         /* Determine the dev_name for the device_node.  This code mimics the
 50          * behavior of of_device_make_bus_id(). We need this because ASoC uses
 51          * the dev_name() of the device to match the platform (DMA) device with
 52          * the CPU (SSI) device.  It's all ugly and hackish, but it works (for
 53          * now).
 54          *
 55          * dai->platform name should already point to an allocated buffer.
 56          */
 57         ret = of_address_to_resource(dma_channel_np, 0, &res);
 58         if (ret) {
 59                 of_node_put(dma_channel_np);
 60                 return ret;
 61         }
 62         snprintf((char *)dai->platforms->name, DAI_NAME_SIZE, "%llx.%pOFn",
 63                  (unsigned long long) res.start, dma_channel_np);
 64 
 65         iprop = of_get_property(dma_channel_np, "cell-index", NULL);
 66         if (!iprop) {
 67                 of_node_put(dma_channel_np);
 68                 return -EINVAL;
 69         }
 70         *dma_channel_id = be32_to_cpup(iprop);
 71 
 72         dma_np = of_get_parent(dma_channel_np);
 73         iprop = of_get_property(dma_np, "cell-index", NULL);
 74         if (!iprop) {
 75                 of_node_put(dma_np);
 76                 of_node_put(dma_channel_np);
 77                 return -EINVAL;
 78         }
 79         *dma_id = be32_to_cpup(iprop);
 80 
 81         of_node_put(dma_np);
 82         of_node_put(dma_channel_np);
 83 
 84         return 0;
 85 }
 86 EXPORT_SYMBOL(fsl_asoc_get_dma_channel);
 87 
 88 /**
 89  * fsl_asoc_get_pll_clocks - get two PLL clock source
 90  *
 91  * @dev: device pointer
 92  * @pll8k_clk: PLL clock pointer for 8kHz
 93  * @pll11k_clk: PLL clock pointer for 11kHz
 94  *
 95  * This function get two PLL clock source
 96  */
 97 void fsl_asoc_get_pll_clocks(struct device *dev, struct clk **pll8k_clk,
 98                              struct clk **pll11k_clk)
 99 {
100         *pll8k_clk = devm_clk_get(dev, "pll8k");
101         if (IS_ERR(*pll8k_clk))
102                 *pll8k_clk = NULL;
103 
104         *pll11k_clk = devm_clk_get(dev, "pll11k");
105         if (IS_ERR(*pll11k_clk))
106                 *pll11k_clk = NULL;
107 }
108 EXPORT_SYMBOL(fsl_asoc_get_pll_clocks);
109 
110 /**
111  * fsl_asoc_reparent_pll_clocks - set clock parent if necessary
112  *
113  * @dev: device pointer
114  * @clk: root clock pointer
115  * @pll8k_clk: PLL clock pointer for 8kHz
116  * @pll11k_clk: PLL clock pointer for 11kHz
117  * @ratio: target requency for root clock
118  *
119  * This function set root clock parent according to the target ratio
120  */
121 void fsl_asoc_reparent_pll_clocks(struct device *dev, struct clk *clk,
122                                   struct clk *pll8k_clk,
123                                   struct clk *pll11k_clk, u64 ratio)
124 {
125         struct clk *p, *pll = NULL, *npll = NULL;
126         bool reparent = false;
127         int ret;
128 
129         if (!clk || !pll8k_clk || !pll11k_clk)
130                 return;
131 
132         p = clk;
133         while (p && pll8k_clk && pll11k_clk) {
134                 struct clk *pp = clk_get_parent(p);
135 
136                 if (clk_is_match(pp, pll8k_clk) ||
137                     clk_is_match(pp, pll11k_clk)) {
138                         pll = pp;
139                         break;
140                 }
141                 p = pp;
142         }
143 
144         npll = (do_div(ratio, 8000) ? pll11k_clk : pll8k_clk);
145         reparent = (pll && !clk_is_match(pll, npll));
146 
147         if (reparent) {
148                 ret = clk_set_parent(p, npll);
149                 if (ret < 0)
150                         dev_warn(dev, "failed to set parent:%d\n", ret);
151         }
152 }
153 EXPORT_SYMBOL(fsl_asoc_reparent_pll_clocks);
154 
155 MODULE_AUTHOR("Timur Tabi <timur@freescale.com>");
156 MODULE_DESCRIPTION("Freescale ASoC utility code");
157 MODULE_LICENSE("GPL v2");
158 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php