2011-03-07 10:47:09 +03:00
/*
* mx27vis - aic32x4 . c
*
* Copyright 2011 Vista Silicon S . L .
*
* Author : Javier Martin < javier . martin @ vista - silicon . com >
*
* 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 .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston ,
* MA 02110 - 1301 , USA .
*/
# include <linux/module.h>
# include <linux/moduleparam.h>
# include <linux/device.h>
# include <linux/i2c.h>
2012-01-20 13:16:57 +04:00
# include <linux/gpio.h>
2012-09-17 09:34:31 +04:00
# include <linux/platform_data/asoc-mx27vis.h>
2011-03-07 10:47:09 +03:00
# include <sound/core.h>
# include <sound/pcm.h>
# include <sound/soc.h>
# include <sound/soc-dapm.h>
2012-01-20 13:16:57 +04:00
# include <sound/tlv.h>
2011-03-07 10:47:09 +03:00
# include <asm/mach-types.h>
# include "../codecs/tlv320aic32x4.h"
# include "imx-ssi.h"
2012-03-05 18:30:53 +04:00
# include "imx-audmux.h"
2011-03-07 10:47:09 +03:00
2012-01-20 13:16:57 +04:00
# define MX27VIS_AMP_GAIN 0
# define MX27VIS_AMP_MUTE 1
static int mx27vis_amp_gain ;
static int mx27vis_amp_mute ;
2012-09-17 09:34:31 +04:00
static int mx27vis_amp_gain0_gpio ;
static int mx27vis_amp_gain1_gpio ;
static int mx27vis_amp_mutel_gpio ;
static int mx27vis_amp_muter_gpio ;
2012-01-20 13:16:57 +04:00
2011-03-07 10:47:09 +03:00
static int mx27vis_aic32x4_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 ;
struct snd_soc_dai * cpu_dai = rtd - > cpu_dai ;
int ret ;
u32 dai_format ;
dai_format = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBM_CFM ;
/* set codec DAI configuration */
snd_soc_dai_set_fmt ( codec_dai , dai_format ) ;
/* set cpu DAI configuration */
snd_soc_dai_set_fmt ( cpu_dai , dai_format ) ;
ret = snd_soc_dai_set_sysclk ( codec_dai , 0 ,
25000000 , SND_SOC_CLOCK_OUT ) ;
if ( ret ) {
pr_err ( " %s: failed setting codec sysclk \n " , __func__ ) ;
return ret ;
}
ret = snd_soc_dai_set_sysclk ( cpu_dai , IMX_SSP_SYS_CLK , 0 ,
SND_SOC_CLOCK_IN ) ;
if ( ret ) {
pr_err ( " can't set CPU system clock IMX_SSP_SYS_CLK \n " ) ;
return ret ;
}
return 0 ;
}
static struct snd_soc_ops mx27vis_aic32x4_snd_ops = {
. hw_params = mx27vis_aic32x4_hw_params ,
} ;
2012-01-20 13:16:57 +04:00
static int mx27vis_amp_set ( struct snd_kcontrol * kcontrol ,
struct snd_ctl_elem_value * ucontrol )
{
struct soc_mixer_control * mc =
( struct soc_mixer_control * ) kcontrol - > private_value ;
int value = ucontrol - > value . integer . value [ 0 ] ;
unsigned int reg = mc - > reg ;
int max = mc - > max ;
if ( value > max )
return - EINVAL ;
switch ( reg ) {
case MX27VIS_AMP_GAIN :
2012-09-17 09:34:31 +04:00
gpio_set_value ( mx27vis_amp_gain0_gpio , value & 1 ) ;
gpio_set_value ( mx27vis_amp_gain1_gpio , value > > 1 ) ;
2012-01-20 13:16:57 +04:00
mx27vis_amp_gain = value ;
break ;
case MX27VIS_AMP_MUTE :
2012-09-17 09:34:31 +04:00
gpio_set_value ( mx27vis_amp_mutel_gpio , value & 1 ) ;
gpio_set_value ( mx27vis_amp_muter_gpio , value > > 1 ) ;
2012-01-20 13:16:57 +04:00
mx27vis_amp_mute = value ;
break ;
}
return 0 ;
}
static int mx27vis_amp_get ( struct snd_kcontrol * kcontrol ,
struct snd_ctl_elem_value * ucontrol )
{
struct soc_mixer_control * mc =
( struct soc_mixer_control * ) kcontrol - > private_value ;
unsigned int reg = mc - > reg ;
switch ( reg ) {
case MX27VIS_AMP_GAIN :
ucontrol - > value . integer . value [ 0 ] = mx27vis_amp_gain ;
break ;
case MX27VIS_AMP_MUTE :
ucontrol - > value . integer . value [ 0 ] = mx27vis_amp_mute ;
break ;
}
return 0 ;
}
/* From 6dB to 24dB in steps of 6dB */
static const DECLARE_TLV_DB_SCALE ( mx27vis_amp_tlv , 600 , 600 , 0 ) ;
2012-01-11 16:21:05 +04:00
static const struct snd_kcontrol_new mx27vis_aic32x4_controls [ ] = {
SOC_DAPM_PIN_SWITCH ( " External Mic " ) ,
2012-01-20 13:16:57 +04:00
SOC_SINGLE_EXT_TLV ( " LO Ext Boost " , MX27VIS_AMP_GAIN , 0 , 3 , 0 ,
mx27vis_amp_get , mx27vis_amp_set , mx27vis_amp_tlv ) ,
SOC_DOUBLE_EXT ( " LO Ext Mute Switch " , MX27VIS_AMP_MUTE , 0 , 1 , 1 , 0 ,
mx27vis_amp_get , mx27vis_amp_set ) ,
2012-01-11 16:21:05 +04:00
} ;
static const struct snd_soc_dapm_widget aic32x4_dapm_widgets [ ] = {
SND_SOC_DAPM_MIC ( " External Mic " , NULL ) ,
} ;
static const struct snd_soc_dapm_route aic32x4_dapm_routes [ ] = {
{ " Mic Bias " , NULL , " External Mic " } ,
{ " IN1_R " , NULL , " Mic Bias " } ,
{ " IN2_R " , NULL , " Mic Bias " } ,
{ " IN3_R " , NULL , " Mic Bias " } ,
{ " IN1_L " , NULL , " Mic Bias " } ,
{ " IN2_L " , NULL , " Mic Bias " } ,
{ " IN3_L " , NULL , " Mic Bias " } ,
} ;
2011-03-07 10:47:09 +03:00
static struct snd_soc_dai_link mx27vis_aic32x4_dai = {
. name = " tlv320aic32x4 " ,
. stream_name = " TLV320AIC32X4 " ,
. codec_dai_name = " tlv320aic32x4-hifi " ,
. platform_name = " imx-pcm-audio.0 " ,
. codec_name = " tlv320aic32x4.0-0018 " ,
. cpu_dai_name = " imx-ssi.0 " ,
. ops = & mx27vis_aic32x4_snd_ops ,
} ;
static struct snd_soc_card mx27vis_aic32x4 = {
. name = " visstrim_m10-audio " ,
2011-12-23 10:47:08 +04:00
. owner = THIS_MODULE ,
2011-03-07 10:47:09 +03:00
. dai_link = & mx27vis_aic32x4_dai ,
. num_links = 1 ,
2012-01-11 16:21:05 +04:00
. controls = mx27vis_aic32x4_controls ,
. num_controls = ARRAY_SIZE ( mx27vis_aic32x4_controls ) ,
. dapm_widgets = aic32x4_dapm_widgets ,
. num_dapm_widgets = ARRAY_SIZE ( aic32x4_dapm_widgets ) ,
. dapm_routes = aic32x4_dapm_routes ,
. num_dapm_routes = ARRAY_SIZE ( aic32x4_dapm_routes ) ,
2011-03-07 10:47:09 +03:00
} ;
2012-03-13 02:48:49 +04:00
static int __devinit mx27vis_aic32x4_probe ( struct platform_device * pdev )
2011-03-07 10:47:09 +03:00
{
2012-09-17 09:34:31 +04:00
struct snd_mx27vis_platform_data * pdata = pdev - > dev . platform_data ;
2011-03-07 10:47:09 +03:00
int ret ;
2012-09-17 09:34:31 +04:00
if ( ! pdata ) {
dev_err ( & pdev - > dev , " No platform data supplied \n " ) ;
return - EINVAL ;
}
mx27vis_amp_gain0_gpio = pdata - > amp_gain0_gpio ;
mx27vis_amp_gain1_gpio = pdata - > amp_gain1_gpio ;
mx27vis_amp_mutel_gpio = pdata - > amp_mutel_gpio ;
mx27vis_amp_muter_gpio = pdata - > amp_muter_gpio ;
2012-03-13 02:48:49 +04:00
mx27vis_aic32x4 . dev = & pdev - > dev ;
ret = snd_soc_register_card ( & mx27vis_aic32x4 ) ;
2011-03-07 10:47:09 +03:00
if ( ret ) {
2012-03-13 02:48:49 +04:00
dev_err ( & pdev - > dev , " snd_soc_register_card failed (%d) \n " ,
ret ) ;
return ret ;
2011-03-07 10:47:09 +03:00
}
/* Connect SSI0 as clock slave to SSI1 external pins */
2012-03-05 18:30:54 +04:00
imx_audmux_v1_configure_port ( MX27_AUDMUX_HPCR1_SSI0 ,
IMX_AUDMUX_V1_PCR_SYN |
IMX_AUDMUX_V1_PCR_TFSDIR |
IMX_AUDMUX_V1_PCR_TCLKDIR |
IMX_AUDMUX_V1_PCR_TFCSEL ( MX27_AUDMUX_PPCR1_SSI_PINS_1 ) |
IMX_AUDMUX_V1_PCR_RXDSEL ( MX27_AUDMUX_PPCR1_SSI_PINS_1 )
2011-03-07 10:47:09 +03:00
) ;
2012-03-05 18:30:54 +04:00
imx_audmux_v1_configure_port ( MX27_AUDMUX_PPCR1_SSI_PINS_1 ,
IMX_AUDMUX_V1_PCR_SYN |
IMX_AUDMUX_V1_PCR_RXDSEL ( MX27_AUDMUX_HPCR1_SSI0 )
2011-03-07 10:47:09 +03:00
) ;
return ret ;
}
2012-03-13 02:48:49 +04:00
static int __devexit mx27vis_aic32x4_remove ( struct platform_device * pdev )
2011-03-07 10:47:09 +03:00
{
2012-03-13 02:48:49 +04:00
snd_soc_unregister_card ( & mx27vis_aic32x4 ) ;
return 0 ;
2011-03-07 10:47:09 +03:00
}
2012-03-13 02:48:49 +04:00
static struct platform_driver mx27vis_aic32x4_audio_driver = {
. driver = {
. name = " mx27vis " ,
. owner = THIS_MODULE ,
} ,
. probe = mx27vis_aic32x4_probe ,
. remove = __devexit_p ( mx27vis_aic32x4_remove ) ,
} ;
module_platform_driver ( mx27vis_aic32x4_audio_driver ) ;
2011-03-07 10:47:09 +03:00
MODULE_AUTHOR ( " Javier Martin <javier.martin@vista-silicon.com> " ) ;
MODULE_DESCRIPTION ( " ALSA SoC AIC32X4 mx27 visstrim " ) ;
MODULE_LICENSE ( " GPL " ) ;
2012-03-13 02:48:49 +04:00
MODULE_ALIAS ( " platform:mx27vis " ) ;