2010-11-22 15:37:25 +09:00
/* sound/soc/samsung/s3c2412-i2s.c
2008-01-10 14:47:21 +01:00
*
* ALSA Soc Audio Layer - S3C2412 I2S driver
*
* Copyright ( c ) 2006 Wolfson Microelectronics PLC .
* Graeme Gregory graeme . gregory @ wolfsonmicro . com
* linux @ wolfsonmicro . com
*
* Copyright ( c ) 2007 , 2004 - 2005 Simtec Electronics
* http : //armlinux.simtec.co.uk/
* Ben Dooks < ben @ simtec . co . uk >
*
* 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/delay.h>
2009-05-13 22:52:24 +01:00
# include <linux/gpio.h>
2008-01-10 14:47:21 +01:00
# include <linux/clk.h>
2009-03-04 00:49:26 +00:00
# include <linux/io.h>
2011-07-15 12:38:28 -04:00
# include <linux/module.h>
2008-01-10 14:47:21 +01:00
# include <sound/soc.h>
2011-01-11 07:26:06 +09:00
# include <sound/pcm_params.h>
2008-01-10 14:47:21 +01:00
2008-08-05 16:14:15 +01:00
# include <mach/dma.h>
2014-01-22 17:30:38 +05:30
# include <mach/gpio-samsung.h>
# include <plat/gpio-cfg.h>
2008-01-10 14:47:21 +01:00
2010-11-22 15:35:57 +09:00
# include "dma.h"
2010-04-27 15:55:21 +09:00
# include "regs-i2s-v2.h"
2008-01-10 14:47:21 +01:00
# include "s3c2412-i2s.h"
2009-11-17 16:53:23 +09:00
static struct s3c_dma_params s3c2412_i2s_pcm_stereo_out = {
2008-01-10 14:47:21 +01:00
. channel = DMACH_I2S_OUT ,
2014-06-23 23:24:04 +03:00
. ch_name = " tx " ,
2008-01-10 14:47:21 +01:00
. dma_size = 4 ,
} ;
2009-11-17 16:53:23 +09:00
static struct s3c_dma_params s3c2412_i2s_pcm_stereo_in = {
2008-01-10 14:47:21 +01:00
. channel = DMACH_I2S_IN ,
2014-06-23 23:24:04 +03:00
. ch_name = " rx " ,
2008-01-10 14:47:21 +01:00
. dma_size = 4 ,
} ;
2009-03-04 00:49:30 +00:00
static struct s3c_i2sv2_info s3c2412_i2s ;
2008-01-10 14:47:21 +01:00
2010-03-17 20:15:21 +00:00
static int s3c2412_i2s_probe ( struct snd_soc_dai * dai )
2008-01-10 14:47:21 +01:00
{
2009-03-04 00:49:30 +00:00
int ret ;
2008-01-10 14:47:21 +01:00
2009-03-06 18:04:34 +00:00
pr_debug ( " Entered %s \n " , __func__ ) ;
2008-01-10 14:47:21 +01:00
2014-06-23 23:24:04 +03:00
samsung_asoc_init_dma_data ( dai , & s3c2412_i2s_pcm_stereo_out ,
& s3c2412_i2s_pcm_stereo_in ) ;
2010-03-17 20:15:21 +00:00
ret = s3c_i2sv2_probe ( dai , & s3c2412_i2s , S3C2410_PA_IIS ) ;
2009-03-04 00:49:30 +00:00
if ( ret )
return ret ;
2008-01-10 14:47:21 +01:00
2009-03-04 00:49:30 +00:00
s3c2412_i2s . dma_capture = & s3c2412_i2s_pcm_stereo_in ;
s3c2412_i2s . dma_playback = & s3c2412_i2s_pcm_stereo_out ;
2008-01-10 14:47:21 +01:00
2014-06-23 23:24:04 +03:00
s3c2412_i2s . iis_cclk = devm_clk_get ( dai - > dev , " i2sclk " ) ;
2011-09-15 10:36:54 +08:00
if ( IS_ERR ( s3c2412_i2s . iis_cclk ) ) {
2009-04-24 16:27:09 +01:00
pr_err ( " failed to get i2sclk clock \n " ) ;
2011-09-15 10:36:54 +08:00
return PTR_ERR ( s3c2412_i2s . iis_cclk ) ;
2008-01-10 14:47:21 +01:00
}
2009-03-04 00:49:30 +00:00
/* Set MPLL as the source for IIS CLK */
2008-01-10 14:47:21 +01:00
2009-03-04 00:49:30 +00:00
clk_set_parent ( s3c2412_i2s . iis_cclk , clk_get ( NULL , " mpll " ) ) ;
2014-06-23 23:24:06 +03:00
clk_prepare_enable ( s3c2412_i2s . iis_cclk ) ;
2008-01-10 14:47:21 +01:00
2009-03-04 00:49:30 +00:00
s3c2412_i2s . iis_cclk = s3c2412_i2s . iis_pclk ;
2008-01-10 14:47:21 +01:00
2012-07-13 19:22:45 +02:00
/* Configure the I2S pins (GPE0...GPE4) in correct mode */
s3c_gpio_cfgall_range ( S3C2410_GPE ( 0 ) , 5 , S3C_GPIO_SFN ( 2 ) ,
S3C_GPIO_PULL_NONE ) ;
2008-01-10 14:47:21 +01:00
2008-01-10 14:48:37 +01:00
return 0 ;
}
2010-03-17 20:15:21 +00:00
static int s3c2412_i2s_remove ( struct snd_soc_dai * dai )
{
2014-06-23 23:24:06 +03:00
clk_disable_unprepare ( s3c2412_i2s . iis_cclk ) ;
2010-03-17 20:15:21 +00:00
return 0 ;
}
2010-03-10 16:48:58 +09:00
static int s3c2412_i2s_hw_params ( struct snd_pcm_substream * substream ,
struct snd_pcm_hw_params * params ,
struct snd_soc_dai * cpu_dai )
{
2010-03-17 20:15:21 +00:00
struct s3c_i2sv2_info * i2s = snd_soc_dai_get_drvdata ( cpu_dai ) ;
2010-03-10 16:48:58 +09:00
u32 iismod ;
pr_debug ( " Entered %s \n " , __func__ ) ;
iismod = readl ( i2s - > regs + S3C2412_IISMOD ) ;
pr_debug ( " %s: r: IISMOD: %x \n " , __func__ , iismod ) ;
2014-05-23 17:35:39 +05:30
switch ( params_width ( params ) ) {
case 8 :
2010-03-10 16:48:58 +09:00
iismod | = S3C2412_IISMOD_8BIT ;
break ;
2014-05-23 17:35:39 +05:30
case 16 :
2010-03-10 16:48:58 +09:00
iismod & = ~ S3C2412_IISMOD_8BIT ;
break ;
}
writel ( iismod , i2s - > regs + S3C2412_IISMOD ) ;
pr_debug ( " %s: w: IISMOD: %x \n " , __func__ , iismod ) ;
return 0 ;
}
2008-01-10 14:47:21 +01:00
# define S3C2412_I2S_RATES \
( SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_16000 | \
SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 )
2011-11-23 11:40:40 +01:00
static const struct snd_soc_dai_ops s3c2412_i2s_dai_ops = {
2010-03-10 16:48:58 +09:00
. hw_params = s3c2412_i2s_hw_params ,
2009-03-03 09:41:00 +08:00
} ;
2010-03-17 20:15:21 +00:00
static struct snd_soc_dai_driver s3c2412_i2s_dai = {
2009-03-04 00:49:30 +00:00
. probe = s3c2412_i2s_probe ,
2010-03-17 20:15:21 +00:00
. remove = s3c2412_i2s_remove ,
2008-01-10 14:47:21 +01:00
. playback = {
. channels_min = 2 ,
. channels_max = 2 ,
. rates = S3C2412_I2S_RATES ,
. formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE ,
} ,
. capture = {
. channels_min = 2 ,
. channels_max = 2 ,
. rates = S3C2412_I2S_RATES ,
. formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE ,
} ,
2009-03-03 09:41:00 +08:00
. ops = & s3c2412_i2s_dai_ops ,
2008-01-10 14:47:21 +01:00
} ;
2010-03-17 20:15:21 +00:00
2013-03-21 03:35:22 -07:00
static const struct snd_soc_component_driver s3c2412_i2s_component = {
. name = " s3c2412-i2s " ,
} ;
2012-12-07 09:26:15 -05:00
static int s3c2412_iis_dev_probe ( struct platform_device * pdev )
2010-03-17 20:15:21 +00:00
{
2012-12-07 13:59:21 +05:30
int ret = 0 ;
2014-06-23 23:24:04 +03:00
struct resource * res ;
res = platform_get_resource ( pdev , IORESOURCE_MEM , 0 ) ;
s3c2412_i2s . regs = devm_ioremap_resource ( & pdev - > dev , res ) ;
2014-07-20 11:43:07 +08:00
if ( IS_ERR ( s3c2412_i2s . regs ) )
return PTR_ERR ( s3c2412_i2s . regs ) ;
2014-06-23 23:24:04 +03:00
s3c2412_i2s_pcm_stereo_out . dma_addr = res - > start + S3C2412_IISTXD ;
s3c2412_i2s_pcm_stereo_in . dma_addr = res - > start + S3C2412_IISRXD ;
2012-12-07 13:59:21 +05:30
2013-03-21 03:35:22 -07:00
ret = s3c_i2sv2_register_component ( & pdev - > dev , - 1 ,
& s3c2412_i2s_component ,
& s3c2412_i2s_dai ) ;
2012-12-07 13:59:21 +05:30
if ( ret ) {
pr_err ( " failed to register the dai \n " ) ;
return ret ;
}
2013-08-22 18:15:02 +05:30
ret = samsung_asoc_dma_platform_register ( & pdev - > dev ) ;
2014-05-21 08:52:19 +05:30
if ( ret )
2012-12-07 13:59:21 +05:30
pr_err ( " failed to register the DMA: %d \n " , ret ) ;
return ret ;
2010-03-17 20:15:21 +00:00
}
static struct platform_driver s3c2412_iis_driver = {
. probe = s3c2412_iis_dev_probe ,
. driver = {
. name = " s3c2412-iis " ,
} ,
} ;
2008-01-10 14:47:21 +01:00
2011-11-23 15:20:13 +00:00
module_platform_driver ( s3c2412_iis_driver ) ;
2008-12-03 19:26:35 +00:00
2008-01-10 14:47:21 +01:00
/* Module information */
MODULE_AUTHOR ( " Ben Dooks, <ben@simtec.co.uk> " ) ;
MODULE_DESCRIPTION ( " S3C2412 I2S SoC Interface " ) ;
MODULE_LICENSE ( " GPL " ) ;
2010-08-12 11:02:19 +01:00
MODULE_ALIAS ( " platform:s3c2412-iis " ) ;