2008-11-19 01:37:32 -05:00
/*
* ASoC driver for Lyrtech SFFSDR board .
*
* Author : Hugo Villeneuve
* Copyright ( C ) 2008 Lyrtech inc
*
* Based on ASoC driver for TI DAVINCI EVM platform , original copyright follow :
* Copyright : ( C ) 2007 MontaVista Software , Inc . , < source @ mvista . 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 .
*/
# include <linux/module.h>
# include <linux/moduleparam.h>
# include <linux/timer.h>
# include <linux/interrupt.h>
# include <linux/platform_device.h>
# include <linux/gpio.h>
# include <sound/core.h>
# include <sound/pcm.h>
# include <sound/soc.h>
# include <sound/soc-dapm.h>
# include <asm/dma.h>
2009-01-05 02:08:30 -08:00
# include <asm/mach-types.h>
2009-01-15 15:40:35 -05:00
# ifdef CONFIG_SFFSDR_FPGA
2008-11-19 01:37:32 -05:00
# include <asm/plat-sffsdr/sffsdr-fpga.h>
2009-01-15 15:40:35 -05:00
# endif
2008-11-19 01:37:32 -05:00
# include <mach/mcbsp.h>
# include <mach/edma.h>
# include "../codecs/pcm3008.h"
# include "davinci-pcm.h"
# include "davinci-i2s.h"
2009-03-09 23:32:07 -04:00
/*
* CLKX and CLKR are the inputs for the Sample Rate Generator .
* FSX and FSR are outputs , driven by the sample Rate Generator .
*/
# define AUDIO_FORMAT (SND_SOC_DAIFMT_DSP_B | \
SND_SOC_DAIFMT_CBM_CFS | \
SND_SOC_DAIFMT_IB_NF )
2008-11-19 01:37:32 -05:00
static int sffsdr_hw_params ( struct snd_pcm_substream * substream ,
2009-03-09 23:32:08 -04:00
struct snd_pcm_hw_params * params )
2008-11-19 01:37:32 -05:00
{
struct snd_soc_pcm_runtime * rtd = substream - > private_data ;
struct snd_soc_dai * cpu_dai = rtd - > dai - > cpu_dai ;
int fs ;
int ret = 0 ;
2009-01-15 15:40:35 -05:00
/* Fsref can be 32000, 44100 or 48000. */
fs = params_rate ( params ) ;
# ifndef CONFIG_SFFSDR_FPGA
/* Without the FPGA module, the Fs is fixed at 44100 Hz */
if ( fs ! = 44100 ) {
pr_debug ( " warning: only 44.1 kHz is supported without SFFSDR FPGA module \n " ) ;
return - EINVAL ;
}
# endif
2009-03-09 23:32:07 -04:00
/* set cpu DAI configuration */
ret = snd_soc_dai_set_fmt ( cpu_dai , AUDIO_FORMAT ) ;
2008-11-19 01:37:32 -05:00
if ( ret < 0 )
return ret ;
pr_debug ( " sffsdr_hw_params: rate = %d Hz \n " , fs ) ;
2009-01-15 15:40:35 -05:00
# ifndef CONFIG_SFFSDR_FPGA
return 0 ;
# else
2008-11-19 01:37:32 -05:00
return sffsdr_fpga_set_codec_fs ( fs ) ;
2009-01-15 15:40:35 -05:00
# endif
2008-11-19 01:37:32 -05:00
}
static struct snd_soc_ops sffsdr_ops = {
. hw_params = sffsdr_hw_params ,
} ;
/* davinci-sffsdr digital audio interface glue - connects codec <--> CPU */
static struct snd_soc_dai_link sffsdr_dai = {
. name = " PCM3008 " , /* Codec name */
. stream_name = " PCM3008 HiFi " ,
. cpu_dai = & davinci_i2s_dai ,
. codec_dai = & pcm3008_dai ,
. ops = & sffsdr_ops ,
} ;
/* davinci-sffsdr audio machine driver */
2008-11-18 20:50:34 +00:00
static struct snd_soc_card snd_soc_sffsdr = {
2008-11-19 01:37:32 -05:00
. name = " DaVinci SFFSDR " ,
2008-12-02 16:01:14 +00:00
. platform = & davinci_soc_platform ,
2008-11-19 01:37:32 -05:00
. dai_link = & sffsdr_dai ,
. num_links = 1 ,
} ;
/* sffsdr audio private data */
static struct pcm3008_setup_data sffsdr_pcm3008_setup = {
. dem0_pin = GPIO ( 45 ) ,
. dem1_pin = GPIO ( 46 ) ,
. pdad_pin = GPIO ( 47 ) ,
. pdda_pin = GPIO ( 38 ) ,
} ;
/* sffsdr audio subsystem */
static struct snd_soc_device sffsdr_snd_devdata = {
2008-11-18 20:50:34 +00:00
. card = & snd_soc_sffsdr ,
2008-11-19 01:37:32 -05:00
. codec_dev = & soc_codec_dev_pcm3008 ,
. codec_data = & sffsdr_pcm3008_setup ,
} ;
static struct resource sffsdr_snd_resources [ ] = {
{
. start = DAVINCI_MCBSP_BASE ,
. end = DAVINCI_MCBSP_BASE + SZ_8K - 1 ,
. flags = IORESOURCE_MEM ,
} ,
} ;
static struct evm_snd_platform_data sffsdr_snd_data = {
. tx_dma_ch = DAVINCI_DMA_MCBSP_TX ,
. rx_dma_ch = DAVINCI_DMA_MCBSP_RX ,
} ;
static struct platform_device * sffsdr_snd_device ;
static int __init sffsdr_init ( void )
{
int ret ;
2009-01-05 02:08:30 -08:00
if ( ! machine_is_sffsdr ( ) )
return - EINVAL ;
2008-11-19 01:37:32 -05:00
sffsdr_snd_device = platform_device_alloc ( " soc-audio " , 0 ) ;
if ( ! sffsdr_snd_device ) {
printk ( KERN_ERR " platform device allocation failed \n " ) ;
return - ENOMEM ;
}
platform_set_drvdata ( sffsdr_snd_device , & sffsdr_snd_devdata ) ;
sffsdr_snd_devdata . dev = & sffsdr_snd_device - > dev ;
2009-02-13 11:36:37 -08:00
platform_device_add_data ( sffsdr_snd_device , & sffsdr_snd_data ,
sizeof ( sffsdr_snd_data ) ) ;
2008-11-19 01:37:32 -05:00
ret = platform_device_add_resources ( sffsdr_snd_device ,
sffsdr_snd_resources ,
ARRAY_SIZE ( sffsdr_snd_resources ) ) ;
if ( ret ) {
printk ( KERN_ERR " platform device add ressources failed \n " ) ;
goto error ;
}
ret = platform_device_add ( sffsdr_snd_device ) ;
if ( ret )
goto error ;
return ret ;
error :
platform_device_put ( sffsdr_snd_device ) ;
return ret ;
}
static void __exit sffsdr_exit ( void )
{
platform_device_unregister ( sffsdr_snd_device ) ;
}
module_init ( sffsdr_init ) ;
module_exit ( sffsdr_exit ) ;
MODULE_AUTHOR ( " Hugo Villeneuve " ) ;
MODULE_DESCRIPTION ( " Lyrtech SFFSDR ASoC driver " ) ;
MODULE_LICENSE ( " GPL " ) ;