2019-04-19 13:21:57 +03:00
// SPDX-License-Identifier: GPL-2.0+
2010-12-20 05:05:57 +03:00
# include "../codecs/wm8994.h"
2011-07-13 15:22:06 +04:00
# include <sound/pcm_params.h>
2013-10-16 14:28:48 +04:00
# include <sound/soc.h>
2011-11-22 06:03:22 +04:00
# include <linux/module.h>
2013-01-18 15:47:06 +04:00
# include <linux/of.h>
2013-07-26 15:42:19 +04:00
# include <linux/of_device.h>
2010-12-20 05:05:57 +03:00
/*
* Default CFG switch settings to use this driver :
* SMDKV310 : CFG5 - 1000 , CFG7 - 111111
*/
/*
* Configure audio route as : -
* $ amixer sset ' DAC1 ' on , on
* $ amixer sset ' Right Headphone Mux ' ' DAC '
* $ amixer sset ' Left Headphone Mux ' ' DAC '
* $ amixer sset ' DAC1R Mixer AIF1 .1 ' on
* $ amixer sset ' DAC1L Mixer AIF1 .1 ' on
* $ amixer sset ' IN2L ' on
* $ amixer sset ' IN2L PGA IN2LN ' on
* $ amixer sset ' MIXINL IN2L ' on
* $ amixer sset ' AIF1ADC1L Mixer ADC / DMIC ' on
* $ amixer sset ' IN2R ' on
* $ amixer sset ' IN2R PGA IN2RN ' on
* $ amixer sset ' MIXINR IN2R ' on
* $ amixer sset ' AIF1ADC1R Mixer ADC / DMIC ' on
*/
/* SMDK has a 16.934MHZ crystal attached to WM8994 */
# define SMDK_WM8994_FREQ 16934000
2013-07-26 15:42:19 +04:00
struct smdk_wm8994_data {
int mclk1_rate ;
} ;
/* Default SMDKs */
static struct smdk_wm8994_data smdk_board_data = {
. mclk1_rate = SMDK_WM8994_FREQ ,
} ;
2010-12-20 05:05:57 +03:00
static int smdk_hw_params ( struct snd_pcm_substream * substream ,
struct snd_pcm_hw_params * params )
{
2023-09-12 02:49:45 +03:00
struct snd_soc_pcm_runtime * rtd = snd_soc_substream_to_rtd ( substream ) ;
struct snd_soc_dai * codec_dai = snd_soc_rtd_to_codec ( rtd , 0 ) ;
2010-12-20 05:05:57 +03:00
unsigned int pll_out ;
int ret ;
/* AIF1CLK should be >=3MHz for optimal performance */
2014-05-23 16:05:39 +04:00
if ( params_width ( params ) = = 24 )
2011-07-13 15:22:06 +04:00
pll_out = params_rate ( params ) * 384 ;
else if ( params_rate ( params ) = = 8000 | | params_rate ( params ) = = 11025 )
2010-12-20 05:05:57 +03:00
pll_out = params_rate ( params ) * 512 ;
else
pll_out = params_rate ( params ) * 256 ;
ret = snd_soc_dai_set_pll ( codec_dai , WM8994_FLL1 , WM8994_FLL_SRC_MCLK1 ,
SMDK_WM8994_FREQ , pll_out ) ;
if ( ret < 0 )
return ret ;
ret = snd_soc_dai_set_sysclk ( codec_dai , WM8994_SYSCLK_FLL1 ,
pll_out , SND_SOC_CLOCK_IN ) ;
if ( ret < 0 )
return ret ;
return 0 ;
}
/*
* SMDK WM8994 DAI operations .
*/
2021-07-28 20:25:48 +03:00
static const struct snd_soc_ops smdk_ops = {
2010-12-20 05:05:57 +03:00
. hw_params = smdk_hw_params ,
} ;
static int smdk_wm8994_init_paiftx ( struct snd_soc_pcm_runtime * rtd )
{
2015-05-03 20:27:07 +03:00
struct snd_soc_dapm_context * dapm = & rtd - > card - > dapm ;
2010-12-20 05:05:57 +03:00
/* Other pins NC */
snd_soc_dapm_nc_pin ( dapm , " HPOUT2P " ) ;
snd_soc_dapm_nc_pin ( dapm , " HPOUT2N " ) ;
snd_soc_dapm_nc_pin ( dapm , " SPKOUTLN " ) ;
snd_soc_dapm_nc_pin ( dapm , " SPKOUTLP " ) ;
snd_soc_dapm_nc_pin ( dapm , " SPKOUTRP " ) ;
snd_soc_dapm_nc_pin ( dapm , " SPKOUTRN " ) ;
snd_soc_dapm_nc_pin ( dapm , " LINEOUT1N " ) ;
snd_soc_dapm_nc_pin ( dapm , " LINEOUT1P " ) ;
snd_soc_dapm_nc_pin ( dapm , " LINEOUT2N " ) ;
snd_soc_dapm_nc_pin ( dapm , " LINEOUT2P " ) ;
snd_soc_dapm_nc_pin ( dapm , " IN1LP " ) ;
snd_soc_dapm_nc_pin ( dapm , " IN2LP:VXRN " ) ;
snd_soc_dapm_nc_pin ( dapm , " IN1RP " ) ;
snd_soc_dapm_nc_pin ( dapm , " IN2RP:VXRP " ) ;
return 0 ;
}
2019-06-06 07:09:06 +03:00
SND_SOC_DAILINK_DEFS ( aif1 ,
DAILINK_COMP_ARRAY ( COMP_CPU ( " samsung-i2s.0 " ) ) ,
2019-06-28 04:48:19 +03:00
DAILINK_COMP_ARRAY ( COMP_CODEC ( " wm8994-codec " , " wm8994-aif1 " ) ) ,
DAILINK_COMP_ARRAY ( COMP_PLATFORM ( " samsung-i2s.0 " ) ) ) ;
2019-06-06 07:09:06 +03:00
SND_SOC_DAILINK_DEFS ( fifo_tx ,
DAILINK_COMP_ARRAY ( COMP_CPU ( " samsung-i2s-sec " ) ) ,
2019-06-28 04:48:19 +03:00
DAILINK_COMP_ARRAY ( COMP_CODEC ( " wm8994-codec " , " wm8994-aif1 " ) ) ,
DAILINK_COMP_ARRAY ( COMP_PLATFORM ( " samsung-i2s-sec " ) ) ) ;
2019-06-06 07:09:06 +03:00
2010-12-20 05:05:57 +03:00
static struct snd_soc_dai_link smdk_dai [ ] = {
{ /* Primary DAI i/f */
. name = " WM8994 AIF1 " ,
. stream_name = " Pri_Dai " ,
. init = smdk_wm8994_init_paiftx ,
2013-07-26 15:01:53 +04:00
. dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBM_CFM ,
2010-12-20 05:05:57 +03:00
. ops = & smdk_ops ,
2019-06-06 07:09:06 +03:00
SND_SOC_DAILINK_REG ( aif1 ) ,
2010-12-20 05:05:57 +03:00
} , { /* Sec_Fifo Playback i/f */
. name = " Sec_FIFO TX " ,
. stream_name = " Sec_Dai " ,
2013-07-26 15:01:53 +04:00
. dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBM_CFM ,
2010-12-20 05:05:57 +03:00
. ops = & smdk_ops ,
2019-06-06 07:09:06 +03:00
SND_SOC_DAILINK_REG ( fifo_tx ) ,
2010-12-20 05:05:57 +03:00
} ,
} ;
static struct snd_soc_card smdk = {
. name = " SMDK-I2S " ,
2011-12-22 06:53:15 +04:00
. owner = THIS_MODULE ,
2010-12-20 05:05:57 +03:00
. dai_link = smdk_dai ,
. num_links = ARRAY_SIZE ( smdk_dai ) ,
} ;
2020-11-25 19:44:23 +03:00
static const struct of_device_id samsung_wm8994_of_match [ ] __maybe_unused = {
2013-07-26 15:42:19 +04:00
{ . compatible = " samsung,smdk-wm8994 " , . data = & smdk_board_data } ,
{ } ,
} ;
MODULE_DEVICE_TABLE ( of , samsung_wm8994_of_match ) ;
2010-12-20 05:05:57 +03:00
2012-12-07 18:26:15 +04:00
static int smdk_audio_probe ( struct platform_device * pdev )
2010-12-20 05:05:57 +03:00
{
int ret ;
2013-01-18 15:47:06 +04:00
struct device_node * np = pdev - > dev . of_node ;
2012-07-03 12:34:04 +04:00
struct snd_soc_card * card = & smdk ;
2013-07-26 15:42:19 +04:00
struct smdk_wm8994_data * board ;
const struct of_device_id * id ;
2010-12-20 05:05:57 +03:00
2012-07-03 12:34:04 +04:00
card - > dev = & pdev - > dev ;
2013-01-18 15:47:06 +04:00
2013-07-26 15:42:19 +04:00
board = devm_kzalloc ( & pdev - > dev , sizeof ( * board ) , GFP_KERNEL ) ;
if ( ! board )
return - ENOMEM ;
2013-01-18 15:47:06 +04:00
if ( np ) {
2019-06-06 07:09:06 +03:00
smdk_dai [ 0 ] . cpus - > dai_name = NULL ;
smdk_dai [ 0 ] . cpus - > of_node = of_parse_phandle ( np ,
2013-01-18 15:47:06 +04:00
" samsung,i2s-controller " , 0 ) ;
2019-06-06 07:09:06 +03:00
if ( ! smdk_dai [ 0 ] . cpus - > of_node ) {
2013-01-18 15:47:06 +04:00
dev_err ( & pdev - > dev ,
" Property 'samsung,i2s-controller' missing or invalid \n " ) ;
ret = - EINVAL ;
2021-02-20 02:09:15 +03:00
return ret ;
2013-01-18 15:47:06 +04:00
}
2019-06-28 04:48:19 +03:00
smdk_dai [ 0 ] . platforms - > name = NULL ;
smdk_dai [ 0 ] . platforms - > of_node = smdk_dai [ 0 ] . cpus - > of_node ;
2013-01-18 15:47:06 +04:00
}
2020-11-25 19:44:52 +03:00
id = of_match_device ( samsung_wm8994_of_match , & pdev - > dev ) ;
2013-07-26 15:42:19 +04:00
if ( id )
* board = * ( ( struct smdk_wm8994_data * ) id - > data ) ;
platform_set_drvdata ( pdev , board ) ;
2013-09-16 21:02:28 +04:00
ret = devm_snd_soc_register_card ( & pdev - > dev , card ) ;
2010-12-20 05:05:57 +03:00
2021-12-14 05:08:41 +03:00
if ( ret )
dev_err_probe ( & pdev - > dev , ret , " snd_soc_register_card() failed \n " ) ;
2010-12-20 05:05:57 +03:00
return ret ;
}
2012-07-03 12:34:04 +04:00
static struct platform_driver smdk_audio_driver = {
. driver = {
2014-02-11 01:25:31 +04:00
. name = " smdk-audio-wm8994 " ,
2013-01-18 15:47:06 +04:00
. of_match_table = of_match_ptr ( samsung_wm8994_of_match ) ,
2013-10-16 14:28:48 +04:00
. pm = & snd_soc_pm_ops ,
2012-07-03 12:34:04 +04:00
} ,
. probe = smdk_audio_probe ,
} ;
module_platform_driver ( smdk_audio_driver ) ;
2010-12-20 05:05:57 +03:00
MODULE_DESCRIPTION ( " ALSA SoC SMDK WM8994 " ) ;
MODULE_LICENSE ( " GPL " ) ;
2013-07-17 20:20:19 +04:00
MODULE_ALIAS ( " platform:smdk-audio-wm8994 " ) ;