2008-01-10 14:47:21 +01:00
/* sound/soc/s3c24xx/s3c2412-i2s.c
*
* 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/init.h>
# include <linux/module.h>
# include <linux/device.h>
# 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>
# include <linux/kernel.h>
2009-03-04 00:49:26 +00:00
# include <linux/io.h>
2008-01-10 14:47:21 +01:00
# include <sound/core.h>
# include <sound/pcm.h>
# include <sound/pcm_params.h>
# include <sound/initval.h>
# include <sound/soc.h>
2008-08-05 16:14:15 +01:00
# include <mach/hardware.h>
2008-01-10 14:47:21 +01:00
2009-03-04 00:49:26 +00:00
# include <plat/regs-s3c2412-iis.h>
2008-01-10 14:47:21 +01:00
2009-03-04 00:49:28 +00:00
# include <plat/audio.h>
2009-04-16 10:32:21 +01:00
# include <mach/regs-gpio.h>
2008-08-05 16:14:15 +01:00
# include <mach/dma.h>
2008-01-10 14:47:21 +01:00
# include "s3c24xx-pcm.h"
# include "s3c2412-i2s.h"
# define S3C2412_I2S_DEBUG 0
static struct s3c2410_dma_client s3c2412_dma_client_out = {
. name = " I2S PCM Stereo out "
} ;
static struct s3c2410_dma_client s3c2412_dma_client_in = {
. name = " I2S PCM Stereo in "
} ;
static struct s3c24xx_pcm_dma_params s3c2412_i2s_pcm_stereo_out = {
. client = & s3c2412_dma_client_out ,
. channel = DMACH_I2S_OUT ,
. dma_addr = S3C2410_PA_IIS + S3C2412_IISTXD ,
. dma_size = 4 ,
} ;
static struct s3c24xx_pcm_dma_params s3c2412_i2s_pcm_stereo_in = {
. client = & s3c2412_dma_client_in ,
. channel = DMACH_I2S_IN ,
. dma_addr = S3C2410_PA_IIS + S3C2412_IISRXD ,
. 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
/*
* Set S3C2412 Clock source
*/
2008-07-07 16:08:24 +01:00
static int s3c2412_i2s_set_sysclk ( struct snd_soc_dai * cpu_dai ,
2008-01-10 14:47:21 +01:00
int clk_id , unsigned int freq , int dir )
{
u32 iismod = readl ( s3c2412_i2s . regs + S3C2412_IISMOD ) ;
2009-03-06 18:04:34 +00:00
pr_debug ( " %s(%p, %d, %u, %d) \n " , __func__ , cpu_dai , clk_id ,
2008-01-10 14:47:21 +01:00
freq , dir ) ;
switch ( clk_id ) {
case S3C2412_CLKSRC_PCLK :
2009-03-04 00:49:30 +00:00
s3c2412_i2s . master = 1 ;
2008-01-10 14:47:21 +01:00
iismod & = ~ S3C2412_IISMOD_MASTER_MASK ;
iismod | = S3C2412_IISMOD_MASTER_INTERNAL ;
break ;
case S3C2412_CLKSRC_I2SCLK :
2009-03-04 00:49:30 +00:00
s3c2412_i2s . master = 0 ;
2008-01-10 14:47:21 +01:00
iismod & = ~ S3C2412_IISMOD_MASTER_MASK ;
iismod | = S3C2412_IISMOD_MASTER_EXTERNAL ;
break ;
default :
return - EINVAL ;
}
writel ( iismod , s3c2412_i2s . regs + S3C2412_IISMOD ) ;
return 0 ;
}
struct clk * s3c2412_get_iisclk ( void )
{
return s3c2412_i2s . iis_clk ;
}
EXPORT_SYMBOL_GPL ( s3c2412_get_iisclk ) ;
2008-06-11 13:47:10 +01:00
static int s3c2412_i2s_probe ( struct platform_device * pdev ,
2008-07-07 16:08:24 +01:00
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
2009-03-04 00:49:30 +00:00
ret = s3c_i2sv2_probe ( pdev , dai , & s3c2412_i2s , S3C2410_PA_IIS ) ;
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
s3c2412_i2s . iis_cclk = clk_get ( & pdev - > dev , " i2sclk " ) ;
if ( s3c2412_i2s . iis_cclk = = NULL ) {
2009-04-24 16:27:09 +01:00
pr_err ( " failed to get i2sclk clock \n " ) ;
2008-01-10 14:47:21 +01:00
iounmap ( s3c2412_i2s . regs ) ;
return - ENODEV ;
}
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 " ) ) ;
2008-01-10 14:47:21 +01:00
clk_enable ( s3c2412_i2s . iis_cclk ) ;
2009-03-04 00:49:30 +00:00
s3c2412_i2s . iis_cclk = s3c2412_i2s . iis_pclk ;
2008-01-10 14:47:21 +01:00
/* Configure the I2S pins in correct mode */
s3c2410_gpio_cfgpin ( S3C2410_GPE0 , S3C2410_GPE0_I2SLRCK ) ;
s3c2410_gpio_cfgpin ( S3C2410_GPE1 , S3C2410_GPE1_I2SSCLK ) ;
s3c2410_gpio_cfgpin ( S3C2410_GPE2 , S3C2410_GPE2_CDCLK ) ;
s3c2410_gpio_cfgpin ( S3C2410_GPE3 , S3C2410_GPE3_I2SSDI ) ;
s3c2410_gpio_cfgpin ( S3C2410_GPE4 , S3C2410_GPE4_I2SSDO ) ;
2008-01-10 14:48:37 +01:00
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 )
2009-03-03 09:41:00 +08:00
static struct snd_soc_dai_ops s3c2412_i2s_dai_ops = {
. set_sysclk = s3c2412_i2s_set_sysclk ,
} ;
2008-07-07 16:08:24 +01:00
struct snd_soc_dai s3c2412_i2s_dai = {
2009-03-04 00:49:30 +00:00
. name = " s3c2412-i2s " ,
. id = 0 ,
. probe = s3c2412_i2s_probe ,
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
} ;
EXPORT_SYMBOL_GPL ( s3c2412_i2s_dai ) ;
2008-12-10 07:47:22 +01:00
static int __init s3c2412_i2s_init ( void )
2008-12-03 19:26:35 +00:00
{
2009-03-04 00:49:30 +00:00
return s3c_i2sv2_register_dai ( & s3c2412_i2s_dai ) ;
2008-12-03 19:26:35 +00:00
}
module_init ( s3c2412_i2s_init ) ;
static void __exit s3c2412_i2s_exit ( void )
{
snd_soc_unregister_dai ( & s3c2412_i2s_dai ) ;
}
module_exit ( s3c2412_i2s_exit ) ;
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 " ) ;