2018-07-24 15:48:32 +03:00
// SPDX-License-Identifier: GPL-2.0
//
// Freescale ALSA SoC Machine driver utility
//
// Author: Timur Tabi <timur@freescale.com>
//
// Copyright 2010 Freescale Semiconductor, Inc.
2012-03-16 12:56:40 +04:00
# include <linux/module.h>
# include <linux/of_address.h>
# include <sound/soc.h>
# include "fsl_utils.h"
/**
* fsl_asoc_get_dma_channel - determine the dma channel for a SSI node
*
* @ ssi_np : pointer to the SSI device tree node
* @ name : name of the phandle pointing to the dma channel
* @ dai : ASoC DAI link pointer to be filled with platform_name
* @ dma_channel_id : dma channel id to be returned
* @ dma_id : dma id to be returned
*
* This function determines the dma and channel id for given SSI node . It
* also discovers the platform_name for the ASoC DAI link .
*/
int fsl_asoc_get_dma_channel ( struct device_node * ssi_np ,
const char * name ,
struct snd_soc_dai_link * dai ,
unsigned int * dma_channel_id ,
unsigned int * dma_id )
{
struct resource res ;
struct device_node * dma_channel_np , * dma_np ;
2018-02-12 00:53:20 +03:00
const __be32 * iprop ;
2012-03-16 12:56:40 +04:00
int ret ;
dma_channel_np = of_parse_phandle ( ssi_np , name , 0 ) ;
if ( ! dma_channel_np )
return - EINVAL ;
if ( ! of_device_is_compatible ( dma_channel_np , " fsl,ssi-dma-channel " ) ) {
of_node_put ( dma_channel_np ) ;
return - EINVAL ;
}
/* Determine the dev_name for the device_node. This code mimics the
* behavior of of_device_make_bus_id ( ) . We need this because ASoC uses
* the dev_name ( ) of the device to match the platform ( DMA ) device with
* the CPU ( SSI ) device . It ' s all ugly and hackish , but it works ( for
* now ) .
*
* dai - > platform name should already point to an allocated buffer .
*/
ret = of_address_to_resource ( dma_channel_np , 0 , & res ) ;
if ( ret ) {
of_node_put ( dma_channel_np ) ;
return ret ;
}
2019-06-06 07:15:25 +03:00
snprintf ( ( char * ) dai - > platforms - > name , DAI_NAME_SIZE , " %llx.%pOFn " ,
2018-08-28 18:44:28 +03:00
( unsigned long long ) res . start , dma_channel_np ) ;
2012-03-16 12:56:40 +04:00
iprop = of_get_property ( dma_channel_np , " cell-index " , NULL ) ;
if ( ! iprop ) {
of_node_put ( dma_channel_np ) ;
return - EINVAL ;
}
* dma_channel_id = be32_to_cpup ( iprop ) ;
dma_np = of_get_parent ( dma_channel_np ) ;
iprop = of_get_property ( dma_np , " cell-index " , NULL ) ;
if ( ! iprop ) {
of_node_put ( dma_np ) ;
2019-02-26 11:17:50 +03:00
of_node_put ( dma_channel_np ) ;
2012-03-16 12:56:40 +04:00
return - EINVAL ;
}
* dma_id = be32_to_cpup ( iprop ) ;
of_node_put ( dma_np ) ;
of_node_put ( dma_channel_np ) ;
return 0 ;
}
EXPORT_SYMBOL ( fsl_asoc_get_dma_channel ) ;
MODULE_AUTHOR ( " Timur Tabi <timur@freescale.com> " ) ;
MODULE_DESCRIPTION ( " Freescale ASoC utility code " ) ;
MODULE_LICENSE ( " GPL v2 " ) ;