1ad47191aSFabio Estevam // SPDX-License-Identifier: GPL-2.0 2ad47191aSFabio Estevam // 3ad47191aSFabio Estevam // Freescale ALSA SoC Machine driver utility 4ad47191aSFabio Estevam // 5ad47191aSFabio Estevam // Author: Timur Tabi <timur@freescale.com> 6ad47191aSFabio Estevam // 7ad47191aSFabio Estevam // Copyright 2010 Freescale Semiconductor, Inc. 860aae8daSShawn Guo 960aae8daSShawn Guo #include <linux/module.h> 1060aae8daSShawn Guo #include <linux/of_address.h> 1160aae8daSShawn Guo #include <sound/soc.h> 1260aae8daSShawn Guo 1360aae8daSShawn Guo #include "fsl_utils.h" 1460aae8daSShawn Guo 1560aae8daSShawn Guo /** 1660aae8daSShawn Guo * fsl_asoc_get_dma_channel - determine the dma channel for a SSI node 1760aae8daSShawn Guo * 1860aae8daSShawn Guo * @ssi_np: pointer to the SSI device tree node 1960aae8daSShawn Guo * @name: name of the phandle pointing to the dma channel 2060aae8daSShawn Guo * @dai: ASoC DAI link pointer to be filled with platform_name 2160aae8daSShawn Guo * @dma_channel_id: dma channel id to be returned 2260aae8daSShawn Guo * @dma_id: dma id to be returned 2360aae8daSShawn Guo * 2460aae8daSShawn Guo * This function determines the dma and channel id for given SSI node. It 2560aae8daSShawn Guo * also discovers the platform_name for the ASoC DAI link. 2660aae8daSShawn Guo */ 2760aae8daSShawn Guo int fsl_asoc_get_dma_channel(struct device_node *ssi_np, 2860aae8daSShawn Guo const char *name, 2960aae8daSShawn Guo struct snd_soc_dai_link *dai, 3060aae8daSShawn Guo unsigned int *dma_channel_id, 3160aae8daSShawn Guo unsigned int *dma_id) 3260aae8daSShawn Guo { 3360aae8daSShawn Guo struct resource res; 3460aae8daSShawn Guo struct device_node *dma_channel_np, *dma_np; 35cb3981b6SFabio Estevam const __be32 *iprop; 3660aae8daSShawn Guo int ret; 3760aae8daSShawn Guo 3860aae8daSShawn Guo dma_channel_np = of_parse_phandle(ssi_np, name, 0); 3960aae8daSShawn Guo if (!dma_channel_np) 4060aae8daSShawn Guo return -EINVAL; 4160aae8daSShawn Guo 4260aae8daSShawn Guo if (!of_device_is_compatible(dma_channel_np, "fsl,ssi-dma-channel")) { 4360aae8daSShawn Guo of_node_put(dma_channel_np); 4460aae8daSShawn Guo return -EINVAL; 4560aae8daSShawn Guo } 4660aae8daSShawn Guo 4760aae8daSShawn Guo /* Determine the dev_name for the device_node. This code mimics the 4860aae8daSShawn Guo * behavior of of_device_make_bus_id(). We need this because ASoC uses 4960aae8daSShawn Guo * the dev_name() of the device to match the platform (DMA) device with 5060aae8daSShawn Guo * the CPU (SSI) device. It's all ugly and hackish, but it works (for 5160aae8daSShawn Guo * now). 5260aae8daSShawn Guo * 5360aae8daSShawn Guo * dai->platform name should already point to an allocated buffer. 5460aae8daSShawn Guo */ 5560aae8daSShawn Guo ret = of_address_to_resource(dma_channel_np, 0, &res); 5660aae8daSShawn Guo if (ret) { 5760aae8daSShawn Guo of_node_put(dma_channel_np); 5860aae8daSShawn Guo return ret; 5960aae8daSShawn Guo } 605d585e1eSRob Herring snprintf((char *)dai->platform_name, DAI_NAME_SIZE, "%llx.%pOFn", 615d585e1eSRob Herring (unsigned long long) res.start, dma_channel_np); 6260aae8daSShawn Guo 6360aae8daSShawn Guo iprop = of_get_property(dma_channel_np, "cell-index", NULL); 6460aae8daSShawn Guo if (!iprop) { 6560aae8daSShawn Guo of_node_put(dma_channel_np); 6660aae8daSShawn Guo return -EINVAL; 6760aae8daSShawn Guo } 6860aae8daSShawn Guo *dma_channel_id = be32_to_cpup(iprop); 6960aae8daSShawn Guo 7060aae8daSShawn Guo dma_np = of_get_parent(dma_channel_np); 7160aae8daSShawn Guo iprop = of_get_property(dma_np, "cell-index", NULL); 7260aae8daSShawn Guo if (!iprop) { 7360aae8daSShawn Guo of_node_put(dma_np); 74c7052471SWen Yang of_node_put(dma_channel_np); 7560aae8daSShawn Guo return -EINVAL; 7660aae8daSShawn Guo } 7760aae8daSShawn Guo *dma_id = be32_to_cpup(iprop); 7860aae8daSShawn Guo 7960aae8daSShawn Guo of_node_put(dma_np); 8060aae8daSShawn Guo of_node_put(dma_channel_np); 8160aae8daSShawn Guo 8260aae8daSShawn Guo return 0; 8360aae8daSShawn Guo } 8460aae8daSShawn Guo EXPORT_SYMBOL(fsl_asoc_get_dma_channel); 8560aae8daSShawn Guo 8660aae8daSShawn Guo MODULE_AUTHOR("Timur Tabi <timur@freescale.com>"); 8760aae8daSShawn Guo MODULE_DESCRIPTION("Freescale ASoC utility code"); 8860aae8daSShawn Guo MODULE_LICENSE("GPL v2"); 89