2018-07-02 09:23:30 +03:00
// SPDX-License-Identifier: GPL-2.0+
//
// soc-util.c -- ALSA SoC Audio Layer utility functions
//
// Copyright 2009 Wolfson Microelectronics PLC.
//
// Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
// Liam Girdwood <lrg@slimlogic.co.uk>
2009-11-10 19:08:04 +03:00
2011-04-27 21:16:32 +04:00
# include <linux/platform_device.h>
2011-09-22 17:34:58 +04:00
# include <linux/export.h>
2009-11-10 19:08:04 +03:00
# include <sound/core.h>
# include <sound/pcm.h>
# include <sound/pcm_params.h>
# include <sound/soc.h>
int snd_soc_calc_frame_size ( int sample_size , int channels , int tdm_slots )
{
return sample_size * channels * tdm_slots ;
}
EXPORT_SYMBOL_GPL ( snd_soc_calc_frame_size ) ;
int snd_soc_params_to_frame_size ( struct snd_pcm_hw_params * params )
{
int sample_size ;
2011-01-31 23:14:38 +03:00
sample_size = snd_pcm_format_width ( params_format ( params ) ) ;
if ( sample_size < 0 )
return sample_size ;
2009-11-10 19:08:04 +03:00
return snd_soc_calc_frame_size ( sample_size , params_channels ( params ) ,
1 ) ;
}
EXPORT_SYMBOL_GPL ( snd_soc_params_to_frame_size ) ;
2009-11-19 14:36:10 +03:00
int snd_soc_calc_bclk ( int fs , int sample_size , int channels , int tdm_slots )
{
return fs * snd_soc_calc_frame_size ( sample_size , channels , tdm_slots ) ;
}
EXPORT_SYMBOL_GPL ( snd_soc_calc_bclk ) ;
2009-11-10 19:08:04 +03:00
int snd_soc_params_to_bclk ( struct snd_pcm_hw_params * params )
{
int ret ;
ret = snd_soc_params_to_frame_size ( params ) ;
if ( ret > 0 )
return ret * params_rate ( params ) ;
else
return ret ;
}
EXPORT_SYMBOL_GPL ( snd_soc_params_to_bclk ) ;
2011-04-27 21:16:32 +04:00
2011-12-06 00:50:45 +04:00
static const struct snd_pcm_hardware dummy_dma_hardware = {
/* Random values to keep userspace happy when checking constraints */
. info = SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER ,
. buffer_bytes_max = 128 * 1024 ,
. period_bytes_min = PAGE_SIZE ,
. period_bytes_max = PAGE_SIZE * 2 ,
. periods_min = 2 ,
. periods_max = 128 ,
} ;
2019-10-02 08:35:05 +03:00
static int dummy_dma_open ( struct snd_soc_component * component ,
struct snd_pcm_substream * substream )
2011-12-06 00:50:45 +04:00
{
2020-07-20 04:17:39 +03:00
struct snd_soc_pcm_runtime * rtd = asoc_substream_to_rtd ( substream ) ;
2013-09-13 21:09:47 +04:00
/* BE's dont need dummy params */
if ( ! rtd - > dai_link - > no_pcm )
snd_soc_set_runtime_hwparams ( substream , & dummy_dma_hardware ) ;
2011-12-06 00:50:45 +04:00
return 0 ;
}
2018-01-29 05:40:52 +03:00
static const struct snd_soc_component_driver dummy_platform = {
2019-10-02 08:35:05 +03:00
. open = dummy_dma_open ,
2011-12-06 00:50:45 +04:00
} ;
2011-04-27 21:16:32 +04:00
2018-01-29 05:58:01 +03:00
static const struct snd_soc_component_driver dummy_codec = {
. idle_bias_on = 1 ,
. use_pmdown_time = 1 ,
. endianness = 1 ,
. non_legacy_dai_naming = 1 ,
} ;
2013-04-17 16:34:06 +04:00
2020-06-27 16:37:10 +03:00
# define STUB_RATES SNDRV_PCM_RATE_8000_384000
2013-04-17 16:34:06 +04:00
# define STUB_FORMATS (SNDRV_PCM_FMTBIT_S8 | \
SNDRV_PCM_FMTBIT_U8 | \
SNDRV_PCM_FMTBIT_S16_LE | \
SNDRV_PCM_FMTBIT_U16_LE | \
SNDRV_PCM_FMTBIT_S24_LE | \
2020-06-27 16:37:10 +03:00
SNDRV_PCM_FMTBIT_S24_3LE | \
2013-04-17 16:34:06 +04:00
SNDRV_PCM_FMTBIT_U24_LE | \
SNDRV_PCM_FMTBIT_S32_LE | \
SNDRV_PCM_FMTBIT_U32_LE | \
SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE )
2015-08-31 18:24:23 +03:00
/*
* The dummy CODEC is only meant to be used in situations where there is no
* actual hardware .
*
* If there is actual hardware even if it does not have a control bus
* the hardware will still have constraints like supported samplerates , etc .
* which should be modelled . And the data flow graph also should be modelled
* using DAPM .
*/
2012-01-09 16:36:24 +04:00
static struct snd_soc_dai_driver dummy_dai = {
. name = " snd-soc-dummy-dai " ,
2013-04-17 16:34:06 +04:00
. playback = {
. stream_name = " Playback " ,
. channels_min = 1 ,
. channels_max = 384 ,
. rates = STUB_RATES ,
. formats = STUB_FORMATS ,
} ,
. capture = {
. stream_name = " Capture " ,
. channels_min = 1 ,
. channels_max = 384 ,
. rates = STUB_RATES ,
. formats = STUB_FORMATS ,
} ,
2012-01-09 16:36:24 +04:00
} ;
2014-01-08 14:40:18 +04:00
int snd_soc_dai_is_dummy ( struct snd_soc_dai * dai )
{
if ( dai - > driver = = & dummy_dai )
return 1 ;
return 0 ;
}
2021-04-16 05:00:26 +03:00
int snd_soc_component_is_dummy ( struct snd_soc_component * component )
{
return ( ( component - > driver = = & dummy_platform ) | |
( component - > driver = = & dummy_codec ) ) ;
}
2012-12-07 18:26:36 +04:00
static int snd_soc_dummy_probe ( struct platform_device * pdev )
2011-04-27 21:16:32 +04:00
{
2012-01-09 16:36:24 +04:00
int ret ;
2018-01-29 05:58:01 +03:00
ret = devm_snd_soc_register_component ( & pdev - > dev ,
& dummy_codec , & dummy_dai , 1 ) ;
2012-01-09 16:36:24 +04:00
if ( ret < 0 )
return ret ;
2018-01-29 05:40:52 +03:00
ret = devm_snd_soc_register_component ( & pdev - > dev , & dummy_platform ,
NULL , 0 ) ;
2012-01-09 16:36:24 +04:00
return ret ;
2011-04-27 21:16:32 +04:00
}
static struct platform_driver soc_dummy_driver = {
. driver = {
. name = " snd-soc-dummy " ,
} ,
. probe = snd_soc_dummy_probe ,
} ;
static struct platform_device * soc_dummy_dev ;
2011-04-28 13:57:54 +04:00
int __init snd_soc_util_init ( void )
2011-04-27 21:16:32 +04:00
{
int ret ;
2013-05-17 13:26:15 +04:00
soc_dummy_dev =
platform_device_register_simple ( " snd-soc-dummy " , - 1 , NULL , 0 ) ;
if ( IS_ERR ( soc_dummy_dev ) )
return PTR_ERR ( soc_dummy_dev ) ;
2011-04-27 21:16:32 +04:00
ret = platform_driver_register ( & soc_dummy_driver ) ;
if ( ret ! = 0 )
platform_device_unregister ( soc_dummy_dev ) ;
return ret ;
}
2011-04-28 13:57:54 +04:00
void __exit snd_soc_util_exit ( void )
2011-04-27 21:16:32 +04:00
{
platform_driver_unregister ( & soc_dummy_driver ) ;
2018-06-26 14:58:35 +03:00
platform_device_unregister ( soc_dummy_dev ) ;
2011-04-27 21:16:32 +04:00
}