2010-05-27 12:58:55 +04:00
/*
* eukrea - tlv320 . c - - SoC audio for eukrea_cpuimxXX in I2S mode
*
* Copyright 2010 Eric Bénard , Eukréa Electromatique < eric @ eukrea . com >
*
* based on sound / soc / s3c24xx / s3c24xx_simtec_tlv320aic23 . c
* which is Copyright 2009 Simtec Electronics
* and on sound / soc / imx / phycore - ac97 . c which is
* Copyright 2009 Sascha Hauer , Pengutronix < s . hauer @ pengutronix . de >
2012-03-16 12:56:38 +04:00
*
2010-05-27 12:58:55 +04:00
* 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 <linux/module.h>
# include <linux/moduleparam.h>
# include <linux/device.h>
# include <linux/i2c.h>
# include <sound/core.h>
# include <sound/pcm.h>
# include <sound/soc.h>
# include <asm/mach-types.h>
# include "../codecs/tlv320aic23.h"
# include "imx-ssi.h"
2012-03-05 18:30:53 +04:00
# include "imx-audmux.h"
2010-05-27 12:58:55 +04:00
# define CODEC_CLOCK 12000000
static int eukrea_tlv320_hw_params ( struct snd_pcm_substream * substream ,
struct snd_pcm_hw_params * params )
{
struct snd_soc_pcm_runtime * rtd = substream - > private_data ;
2010-11-04 19:05:40 +03:00
struct snd_soc_dai * codec_dai = rtd - > codec_dai ;
struct snd_soc_dai * cpu_dai = rtd - > cpu_dai ;
2010-05-27 12:58:55 +04:00
int ret ;
ret = snd_soc_dai_set_fmt ( cpu_dai , SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBM_CFM ) ;
if ( ret ) {
pr_err ( " %s: failed set cpu dai format \n " , __func__ ) ;
return ret ;
}
ret = snd_soc_dai_set_fmt ( codec_dai , SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_NB_NF |
SND_SOC_DAIFMT_CBM_CFM ) ;
if ( ret ) {
pr_err ( " %s: failed set codec dai format \n " , __func__ ) ;
return ret ;
}
ret = snd_soc_dai_set_sysclk ( codec_dai , 0 ,
CODEC_CLOCK , SND_SOC_CLOCK_OUT ) ;
if ( ret ) {
pr_err ( " %s: failed setting codec sysclk \n " , __func__ ) ;
return ret ;
}
2010-06-17 17:44:01 +04:00
snd_soc_dai_set_tdm_slot ( cpu_dai , 0xffffffc , 0xffffffc , 2 , 0 ) ;
2010-05-27 12:58:55 +04:00
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 eukrea_tlv320_snd_ops = {
. hw_params = eukrea_tlv320_hw_params ,
} ;
static struct snd_soc_dai_link eukrea_tlv320_dai = {
. name = " tlv320aic23 " ,
. stream_name = " TLV320AIC23 " ,
2010-11-04 19:05:40 +03:00
. codec_dai_name = " tlv320aic23-hifi " ,
2013-04-25 07:18:49 +04:00
. platform_name = " imx-ssi.0 " ,
2010-03-17 23:15:21 +03:00
. codec_name = " tlv320aic23-codec.0-001a " ,
2010-11-04 19:05:40 +03:00
. cpu_dai_name = " imx-ssi.0 " ,
2010-05-27 12:58:55 +04:00
. ops = & eukrea_tlv320_snd_ops ,
} ;
static struct snd_soc_card eukrea_tlv320 = {
. name = " cpuimx-audio " ,
2011-12-23 10:47:08 +04:00
. owner = THIS_MODULE ,
2010-05-27 12:58:55 +04:00
. dai_link = & eukrea_tlv320_dai ,
. num_links = 1 ,
} ;
2012-12-07 18:26:16 +04:00
static int eukrea_tlv320_probe ( struct platform_device * pdev )
2010-05-27 12:58:55 +04:00
{
int ret ;
2012-03-05 18:30:49 +04:00
int int_port = 0 , ext_port ;
if ( machine_is_eukrea_cpuimx27 ( ) ) {
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_RFSDIR |
IMX_AUDMUX_V1_PCR_RCLKDIR |
IMX_AUDMUX_V1_PCR_TFCSEL ( MX27_AUDMUX_HPCR3_SSI_PINS_4 ) |
IMX_AUDMUX_V1_PCR_RFCSEL ( MX27_AUDMUX_HPCR3_SSI_PINS_4 ) |
IMX_AUDMUX_V1_PCR_RXDSEL ( MX27_AUDMUX_HPCR3_SSI_PINS_4 )
2012-03-05 18:30:49 +04:00
) ;
2012-03-05 18:30:54 +04:00
imx_audmux_v1_configure_port ( MX27_AUDMUX_HPCR3_SSI_PINS_4 ,
IMX_AUDMUX_V1_PCR_SYN |
IMX_AUDMUX_V1_PCR_RXDSEL ( MX27_AUDMUX_HPCR1_SSI0 )
2012-03-05 18:30:49 +04:00
) ;
} else if ( machine_is_eukrea_cpuimx25sd ( ) | |
machine_is_eukrea_cpuimx35sd ( ) | |
machine_is_eukrea_cpuimx51sd ( ) ) {
ext_port = machine_is_eukrea_cpuimx25sd ( ) ? 4 : 3 ;
2012-03-05 18:30:54 +04:00
imx_audmux_v2_configure_port ( int_port ,
IMX_AUDMUX_V2_PTCR_SYN |
IMX_AUDMUX_V2_PTCR_TFSDIR |
IMX_AUDMUX_V2_PTCR_TFSEL ( ext_port ) |
IMX_AUDMUX_V2_PTCR_TCLKDIR |
IMX_AUDMUX_V2_PTCR_TCSEL ( ext_port ) ,
IMX_AUDMUX_V2_PDCR_RXDSEL ( ext_port )
2012-03-05 18:30:49 +04:00
) ;
2012-03-05 18:30:54 +04:00
imx_audmux_v2_configure_port ( ext_port ,
IMX_AUDMUX_V2_PTCR_SYN ,
IMX_AUDMUX_V2_PDCR_RXDSEL ( int_port )
2012-03-05 18:30:49 +04:00
) ;
} else {
2010-05-27 12:58:55 +04:00
/* return happy. We might run on a totally different machine */
return 0 ;
2012-03-05 18:30:49 +04:00
}
2010-05-27 12:58:55 +04:00
2012-09-22 19:27:31 +04:00
eukrea_tlv320 . dev = & pdev - > dev ;
ret = snd_soc_register_card ( & eukrea_tlv320 ) ;
if ( ret )
dev_err ( & pdev - > dev , " snd_soc_register_card failed (%d) \n " , ret ) ;
2010-05-27 12:58:55 +04:00
return ret ;
}
2012-12-07 18:26:16 +04:00
static int eukrea_tlv320_remove ( struct platform_device * pdev )
2010-05-27 12:58:55 +04:00
{
2012-09-22 19:27:31 +04:00
snd_soc_unregister_card ( & eukrea_tlv320 ) ;
return 0 ;
2010-05-27 12:58:55 +04:00
}
2012-09-22 19:27:31 +04:00
static struct platform_driver eukrea_tlv320_driver = {
. driver = {
. name = " eukrea_tlv320 " ,
. owner = THIS_MODULE ,
} ,
. probe = eukrea_tlv320_probe ,
2012-12-07 18:26:16 +04:00
. remove = eukrea_tlv320_remove , } ;
2012-09-22 19:27:31 +04:00
module_platform_driver ( eukrea_tlv320_driver ) ;
2010-05-27 12:58:55 +04:00
MODULE_AUTHOR ( " Eric Bénard <eric@eukrea.com> " ) ;
MODULE_DESCRIPTION ( " CPUIMX ALSA SoC driver " ) ;
MODULE_LICENSE ( " GPL " ) ;
2012-09-22 19:27:31 +04:00
MODULE_ALIAS ( " platform:eukrea_tlv320 " ) ;