2009-06-11 17:35:27 -05:00
/*
* zoom2 . c - - SoC audio for Zoom2
*
* Author : Misael Lopez Cruz < x0052729 @ ti . com >
*
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation .
*
* 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 St , Fifth Floor , Boston , MA
* 02110 - 1301 USA
*
*/
# include <linux/clk.h>
# include <linux/platform_device.h>
# include <sound/core.h>
# include <sound/pcm.h>
# include <sound/soc.h>
# include <asm/mach-types.h>
# include <mach/hardware.h>
# include <mach/gpio.h>
2010-03-17 20:15:21 +00:00
# include <mach/board-zoom.h>
2009-10-20 09:40:47 -07:00
# include <plat/mcbsp.h>
2009-06-11 17:35:27 -05:00
2010-03-17 20:15:21 +00:00
/* Register descriptions for twl4030 codec part */
2011-05-31 12:02:49 +03:00
# include <linux/mfd/twl4030-audio.h>
2010-03-17 20:15:21 +00:00
2009-06-11 17:35:27 -05:00
# include "omap-mcbsp.h"
# include "omap-pcm.h"
2009-07-02 19:04:07 -05:00
# define ZOOM2_HEADSET_MUX_GPIO (OMAP_MAX_GPIO_LINES + 15)
2009-06-11 17:35:27 -05:00
static int zoom2_hw_params ( struct snd_pcm_substream * substream ,
struct snd_pcm_hw_params * params )
{
struct snd_soc_pcm_runtime * rtd = substream - > private_data ;
2010-03-17 20:15:21 +00:00
struct snd_soc_dai * codec_dai = rtd - > codec_dai ;
struct snd_soc_dai * cpu_dai = rtd - > cpu_dai ;
2009-06-11 17:35:27 -05:00
int ret ;
/* Set codec DAI configuration */
ret = snd_soc_dai_set_fmt ( codec_dai ,
SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBM_CFM ) ;
if ( ret < 0 ) {
printk ( KERN_ERR " can't set codec DAI configuration \n " ) ;
return ret ;
}
/* Set cpu DAI configuration */
ret = snd_soc_dai_set_fmt ( cpu_dai ,
SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBM_CFM ) ;
if ( ret < 0 ) {
printk ( KERN_ERR " can't set cpu DAI configuration \n " ) ;
return ret ;
}
/* Set the codec system clock for DAC and ADC */
ret = snd_soc_dai_set_sysclk ( codec_dai , 0 , 26000000 ,
SND_SOC_CLOCK_IN ) ;
if ( ret < 0 ) {
printk ( KERN_ERR " can't set codec system clock \n " ) ;
return ret ;
}
return 0 ;
}
static struct snd_soc_ops zoom2_ops = {
. hw_params = zoom2_hw_params ,
} ;
static int zoom2_hw_voice_params ( struct snd_pcm_substream * substream ,
struct snd_pcm_hw_params * params )
{
struct snd_soc_pcm_runtime * rtd = substream - > private_data ;
2010-03-17 20:15:21 +00:00
struct snd_soc_dai * codec_dai = rtd - > codec_dai ;
struct snd_soc_dai * cpu_dai = rtd - > cpu_dai ;
2009-06-11 17:35:27 -05:00
int ret ;
/* Set codec DAI configuration */
ret = snd_soc_dai_set_fmt ( codec_dai ,
SND_SOC_DAIFMT_DSP_A |
SND_SOC_DAIFMT_IB_NF |
2009-06-19 03:23:42 -05:00
SND_SOC_DAIFMT_CBM_CFM ) ;
2009-06-11 17:35:27 -05:00
if ( ret ) {
printk ( KERN_ERR " can't set codec DAI configuration \n " ) ;
return ret ;
}
/* Set cpu DAI configuration */
ret = snd_soc_dai_set_fmt ( cpu_dai ,
SND_SOC_DAIFMT_DSP_A |
SND_SOC_DAIFMT_IB_NF |
SND_SOC_DAIFMT_CBM_CFM ) ;
if ( ret < 0 ) {
printk ( KERN_ERR " can't set cpu DAI configuration \n " ) ;
return ret ;
}
/* Set the codec system clock for DAC and ADC */
ret = snd_soc_dai_set_sysclk ( codec_dai , 0 , 26000000 ,
SND_SOC_CLOCK_IN ) ;
if ( ret < 0 ) {
printk ( KERN_ERR " can't set codec system clock \n " ) ;
return ret ;
}
return 0 ;
}
static struct snd_soc_ops zoom2_voice_ops = {
. hw_params = zoom2_hw_voice_params ,
} ;
/* Zoom2 machine DAPM */
static const struct snd_soc_dapm_widget zoom2_twl4030_dapm_widgets [ ] = {
SND_SOC_DAPM_MIC ( " Ext Mic " , NULL ) ,
SND_SOC_DAPM_SPK ( " Ext Spk " , NULL ) ,
SND_SOC_DAPM_MIC ( " Headset Mic " , NULL ) ,
SND_SOC_DAPM_HP ( " Headset Stereophone " , NULL ) ,
SND_SOC_DAPM_LINE ( " Aux In " , NULL ) ,
} ;
static const struct snd_soc_dapm_route audio_map [ ] = {
/* External Mics: MAINMIC, SUBMIC with bias*/
{ " MAINMIC " , NULL , " Mic Bias 1 " } ,
{ " SUBMIC " , NULL , " Mic Bias 2 " } ,
{ " Mic Bias 1 " , NULL , " Ext Mic " } ,
{ " Mic Bias 2 " , NULL , " Ext Mic " } ,
/* External Speakers: HFL, HFR */
{ " Ext Spk " , NULL , " HFL " } ,
{ " Ext Spk " , NULL , " HFR " } ,
/* Headset Stereophone: HSOL, HSOR */
{ " Headset Stereophone " , NULL , " HSOL " } ,
{ " Headset Stereophone " , NULL , " HSOR " } ,
/* Headset Mic: HSMIC with bias */
{ " HSMIC " , NULL , " Headset Mic Bias " } ,
{ " Headset Mic Bias " , NULL , " Headset Mic " } ,
/* Aux In: AUXL, AUXR */
{ " Aux In " , NULL , " AUXL " } ,
{ " Aux In " , NULL , " AUXR " } ,
} ;
2010-03-17 20:15:21 +00:00
static int zoom2_twl4030_init ( struct snd_soc_pcm_runtime * rtd )
2009-06-11 17:35:27 -05:00
{
2010-03-17 20:15:21 +00:00
struct snd_soc_codec * codec = rtd - > codec ;
2010-11-05 15:53:46 +02:00
struct snd_soc_dapm_context * dapm = & codec - > dapm ;
2009-06-11 17:35:27 -05:00
int ret ;
/* Add Zoom2 specific widgets */
2010-11-05 15:53:46 +02:00
ret = snd_soc_dapm_new_controls ( dapm , zoom2_twl4030_dapm_widgets ,
2009-06-11 17:35:27 -05:00
ARRAY_SIZE ( zoom2_twl4030_dapm_widgets ) ) ;
if ( ret )
return ret ;
/* Set up Zoom2 specific audio path audio_map */
2010-11-05 15:53:46 +02:00
snd_soc_dapm_add_routes ( dapm , audio_map , ARRAY_SIZE ( audio_map ) ) ;
2009-06-11 17:35:27 -05:00
/* Zoom2 connected pins */
2010-11-05 15:53:46 +02:00
snd_soc_dapm_enable_pin ( dapm , " Ext Mic " ) ;
snd_soc_dapm_enable_pin ( dapm , " Ext Spk " ) ;
snd_soc_dapm_enable_pin ( dapm , " Headset Mic " ) ;
snd_soc_dapm_enable_pin ( dapm , " Headset Stereophone " ) ;
snd_soc_dapm_enable_pin ( dapm , " Aux In " ) ;
2009-06-11 17:35:27 -05:00
/* TWL4030 not connected pins */
2010-11-05 15:53:46 +02:00
snd_soc_dapm_nc_pin ( dapm , " CARKITMIC " ) ;
snd_soc_dapm_nc_pin ( dapm , " DIGIMIC0 " ) ;
snd_soc_dapm_nc_pin ( dapm , " DIGIMIC1 " ) ;
snd_soc_dapm_nc_pin ( dapm , " EARPIECE " ) ;
snd_soc_dapm_nc_pin ( dapm , " PREDRIVEL " ) ;
snd_soc_dapm_nc_pin ( dapm , " PREDRIVER " ) ;
snd_soc_dapm_nc_pin ( dapm , " CARKITL " ) ;
snd_soc_dapm_nc_pin ( dapm , " CARKITR " ) ;
ret = snd_soc_dapm_sync ( dapm ) ;
2009-06-11 17:35:27 -05:00
return ret ;
}
2010-03-17 20:15:21 +00:00
static int zoom2_twl4030_voice_init ( struct snd_soc_pcm_runtime * rtd )
2009-06-11 17:35:27 -05:00
{
2010-03-17 20:15:21 +00:00
struct snd_soc_codec * codec = rtd - > codec ;
2009-06-11 17:35:27 -05:00
unsigned short reg ;
/* Enable voice interface */
2010-03-17 20:15:21 +00:00
reg = codec - > driver - > read ( codec , TWL4030_REG_VOICE_IF ) ;
2009-06-11 17:35:27 -05:00
reg | = TWL4030_VIF_DIN_EN | TWL4030_VIF_DOUT_EN | TWL4030_VIF_EN ;
2010-03-17 20:15:21 +00:00
codec - > driver - > write ( codec , TWL4030_REG_VOICE_IF , reg ) ;
2009-06-11 17:35:27 -05:00
return 0 ;
}
/* Digital audio interface glue - connects codec <--> CPU */
static struct snd_soc_dai_link zoom2_dai [ ] = {
{
. name = " TWL4030 I2S " ,
. stream_name = " TWL4030 Audio " ,
2010-03-17 20:15:21 +00:00
. cpu_dai_name = " omap-mcbsp-dai.1 " ,
. codec_dai_name = " twl4030-hifi " ,
. platform_name = " omap-pcm-audio " ,
. codec_name = " twl4030-codec " ,
2009-06-11 17:35:27 -05:00
. init = zoom2_twl4030_init ,
. ops = & zoom2_ops ,
} ,
{
. name = " TWL4030 PCM " ,
. stream_name = " TWL4030 Voice " ,
2010-03-17 20:15:21 +00:00
. cpu_dai_name = " omap-mcbsp-dai.2 " ,
. codec_dai_name = " twl4030-voice " ,
. platform_name = " omap-pcm-audio " ,
. codec_name = " twl4030-codec " ,
2009-06-11 17:35:27 -05:00
. init = zoom2_twl4030_voice_init ,
. ops = & zoom2_voice_ops ,
} ,
} ;
/* Audio machine driver */
static struct snd_soc_card snd_soc_zoom2 = {
. name = " Zoom2 " ,
. dai_link = zoom2_dai ,
. num_links = ARRAY_SIZE ( zoom2_dai ) ,
} ;
static struct platform_device * zoom2_snd_device ;
static int __init zoom2_soc_init ( void )
{
int ret ;
2010-10-06 16:47:26 +03:00
if ( ! machine_is_omap_zoom2 ( ) )
2009-06-11 17:35:27 -05:00
return - ENODEV ;
printk ( KERN_INFO " Zoom2 SoC init \n " ) ;
zoom2_snd_device = platform_device_alloc ( " soc-audio " , - 1 ) ;
if ( ! zoom2_snd_device ) {
printk ( KERN_ERR " Platform device allocation failed \n " ) ;
return - ENOMEM ;
}
2010-03-17 20:15:21 +00:00
platform_set_drvdata ( zoom2_snd_device , & snd_soc_zoom2 ) ;
2009-06-11 17:35:27 -05:00
ret = platform_device_add ( zoom2_snd_device ) ;
if ( ret )
goto err1 ;
BUG_ON ( gpio_request ( ZOOM2_HEADSET_MUX_GPIO , " hs_mux " ) < 0 ) ;
gpio_direction_output ( ZOOM2_HEADSET_MUX_GPIO , 0 ) ;
2009-07-02 19:04:07 -05:00
BUG_ON ( gpio_request ( ZOOM2_HEADSET_EXTMUTE_GPIO , " ext_mute " ) < 0 ) ;
gpio_direction_output ( ZOOM2_HEADSET_EXTMUTE_GPIO , 0 ) ;
2009-06-11 17:35:27 -05:00
return 0 ;
err1 :
printk ( KERN_ERR " Unable to add platform device \n " ) ;
platform_device_put ( zoom2_snd_device ) ;
return ret ;
}
module_init ( zoom2_soc_init ) ;
static void __exit zoom2_soc_exit ( void )
{
gpio_free ( ZOOM2_HEADSET_MUX_GPIO ) ;
2009-07-02 19:04:07 -05:00
gpio_free ( ZOOM2_HEADSET_EXTMUTE_GPIO ) ;
2009-06-11 17:35:27 -05:00
platform_device_unregister ( zoom2_snd_device ) ;
}
module_exit ( zoom2_soc_exit ) ;
MODULE_AUTHOR ( " Misael Lopez Cruz <x0052729@ti.com> " ) ;
MODULE_DESCRIPTION ( " ALSA SoC Zoom2 " ) ;
MODULE_LICENSE ( " GPL " ) ;