2010-12-20 11:05:57 +09:00
/*
* smdk_wm8994 . c
*
* This program is free software ; you can redistribute it and / or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation ; either version 2 of the License , or ( at your
* option ) any later version .
*/
# include "../codecs/wm8994.h"
2011-07-13 16:52:06 +05:30
# include <sound/pcm_params.h>
2013-10-16 15:58:48 +05:30
# include <sound/soc.h>
2011-11-22 11:03:22 +09:00
# include <linux/module.h>
2013-01-18 17:17:06 +05:30
# include <linux/of.h>
2013-07-26 12:42:19 +01:00
# include <linux/of_device.h>
2010-12-20 11:05:57 +09: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 12:42:19 +01: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 11:05:57 +09:00
static int smdk_hw_params ( struct snd_pcm_substream * substream ,
struct snd_pcm_hw_params * params )
{
struct snd_soc_pcm_runtime * rtd = substream - > private_data ;
struct snd_soc_dai * codec_dai = rtd - > codec_dai ;
unsigned int pll_out ;
int ret ;
/* AIF1CLK should be >=3MHz for optimal performance */
2014-05-23 17:35:39 +05:30
if ( params_width ( params ) = = 24 )
2011-07-13 16:52:06 +05:30
pll_out = params_rate ( params ) * 384 ;
else if ( params_rate ( params ) = = 8000 | | params_rate ( params ) = = 11025 )
2010-12-20 11:05:57 +09: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 .
*/
static struct snd_soc_ops smdk_ops = {
. hw_params = smdk_hw_params ,
} ;
static int smdk_wm8994_init_paiftx ( struct snd_soc_pcm_runtime * rtd )
{
struct snd_soc_codec * codec = rtd - > codec ;
struct snd_soc_dapm_context * dapm = & codec - > dapm ;
/* 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 ;
}
static struct snd_soc_dai_link smdk_dai [ ] = {
{ /* Primary DAI i/f */
. name = " WM8994 AIF1 " ,
. stream_name = " Pri_Dai " ,
. cpu_dai_name = " samsung-i2s.0 " ,
. codec_dai_name = " wm8994-aif1 " ,
2012-12-07 13:59:21 +05:30
. platform_name = " samsung-i2s.0 " ,
2010-12-20 11:05:57 +09:00
. codec_name = " wm8994-codec " ,
. init = smdk_wm8994_init_paiftx ,
2013-07-26 12:01:53 +01:00
. dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBM_CFM ,
2010-12-20 11:05:57 +09:00
. ops = & smdk_ops ,
} , { /* Sec_Fifo Playback i/f */
. name = " Sec_FIFO TX " ,
. stream_name = " Sec_Dai " ,
2013-01-18 17:17:00 +05:30
. cpu_dai_name = " samsung-i2s-sec " ,
2010-12-20 11:05:57 +09:00
. codec_dai_name = " wm8994-aif1 " ,
2013-01-18 17:17:00 +05:30
. platform_name = " samsung-i2s-sec " ,
2010-12-20 11:05:57 +09:00
. codec_name = " wm8994-codec " ,
2013-07-26 12:01:53 +01:00
. dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBM_CFM ,
2010-12-20 11:05:57 +09:00
. ops = & smdk_ops ,
} ,
} ;
static struct snd_soc_card smdk = {
. name = " SMDK-I2S " ,
2011-12-22 10:53:15 +08:00
. owner = THIS_MODULE ,
2010-12-20 11:05:57 +09:00
. dai_link = smdk_dai ,
. num_links = ARRAY_SIZE ( smdk_dai ) ,
} ;
2013-07-26 12:42:19 +01:00
static const struct of_device_id samsung_wm8994_of_match [ ] = {
{ . compatible = " samsung,smdk-wm8994 " , . data = & smdk_board_data } ,
{ } ,
} ;
MODULE_DEVICE_TABLE ( of , samsung_wm8994_of_match ) ;
2010-12-20 11:05:57 +09:00
2012-12-07 09:26:15 -05:00
static int smdk_audio_probe ( struct platform_device * pdev )
2010-12-20 11:05:57 +09:00
{
int ret ;
2013-01-18 17:17:06 +05:30
struct device_node * np = pdev - > dev . of_node ;
2012-07-03 14:04:04 +05:30
struct snd_soc_card * card = & smdk ;
2013-07-26 12:42:19 +01:00
struct smdk_wm8994_data * board ;
const struct of_device_id * id ;
2010-12-20 11:05:57 +09:00
2012-07-03 14:04:04 +05:30
card - > dev = & pdev - > dev ;
2013-01-18 17:17:06 +05:30
2013-07-26 12:42:19 +01:00
board = devm_kzalloc ( & pdev - > dev , sizeof ( * board ) , GFP_KERNEL ) ;
if ( ! board )
return - ENOMEM ;
2013-01-18 17:17:06 +05:30
if ( np ) {
smdk_dai [ 0 ] . cpu_dai_name = NULL ;
smdk_dai [ 0 ] . cpu_of_node = of_parse_phandle ( np ,
" samsung,i2s-controller " , 0 ) ;
if ( ! smdk_dai [ 0 ] . cpu_of_node ) {
dev_err ( & pdev - > dev ,
" Property 'samsung,i2s-controller' missing or invalid \n " ) ;
ret = - EINVAL ;
}
smdk_dai [ 0 ] . platform_name = NULL ;
smdk_dai [ 0 ] . platform_of_node = smdk_dai [ 0 ] . cpu_of_node ;
}
2014-01-22 17:30:43 +05:30
id = of_match_device ( of_match_ptr ( samsung_wm8994_of_match ) , & pdev - > dev ) ;
2013-07-26 12:42:19 +01:00
if ( id )
* board = * ( ( struct smdk_wm8994_data * ) id - > data ) ;
platform_set_drvdata ( pdev , board ) ;
2013-09-16 18:02:28 +01:00
ret = devm_snd_soc_register_card ( & pdev - > dev , card ) ;
2010-12-20 11:05:57 +09:00
if ( ret )
2012-07-03 14:04:04 +05:30
dev_err ( & pdev - > dev , " snd_soc_register_card() failed:%d \n " , ret ) ;
2010-12-20 11:05:57 +09:00
return ret ;
}
2012-07-03 14:04:04 +05:30
static struct platform_driver smdk_audio_driver = {
. driver = {
2014-02-10 22:25:31 +01:00
. name = " smdk-audio-wm8994 " ,
2012-07-03 14:04:04 +05:30
. owner = THIS_MODULE ,
2013-01-18 17:17:06 +05:30
. of_match_table = of_match_ptr ( samsung_wm8994_of_match ) ,
2013-10-16 15:58:48 +05:30
. pm = & snd_soc_pm_ops ,
2012-07-03 14:04:04 +05:30
} ,
. probe = smdk_audio_probe ,
} ;
module_platform_driver ( smdk_audio_driver ) ;
2010-12-20 11:05:57 +09:00
MODULE_DESCRIPTION ( " ALSA SoC SMDK WM8994 " ) ;
MODULE_LICENSE ( " GPL " ) ;
2013-07-17 17:20:19 +01:00
MODULE_ALIAS ( " platform:smdk-audio-wm8994 " ) ;