2007-02-14 15:17:49 +03:00
/*
* s3c24xx - i2s . c - - ALSA Soc Audio Layer
*
* ( c ) 2006 Wolfson Microelectronics PLC .
* Graeme Gregory graeme . gregory @ wolfsonmicro . com or linux @ wolfsonmicro . com
*
2009-02-28 20:09:57 +03:00
* Copyright 2004 - 2005 Simtec Electronics
2007-02-14 15:17:49 +03:00
* 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>
# include <linux/clk.h>
2008-01-07 15:33:45 +03:00
# include <linux/jiffies.h>
2008-04-23 17:09:31 +04:00
# include <linux/io.h>
2007-02-14 15:17:49 +03: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 19:14:15 +04:00
# include <mach/hardware.h>
# include <mach/regs-gpio.h>
# include <mach/regs-clock.h>
2009-03-04 03:49:28 +03:00
# include <plat/audio.h>
2007-02-14 15:17:49 +03:00
# include <asm/dma.h>
2008-08-05 19:14:15 +04:00
# include <mach/dma.h>
2007-02-14 15:17:49 +03:00
2009-03-04 03:49:26 +03:00
# include <plat/regs-iis.h>
2007-12-19 17:37:49 +03:00
2007-02-14 15:17:49 +03:00
# include "s3c24xx-pcm.h"
# include "s3c24xx-i2s.h"
static struct s3c2410_dma_client s3c24xx_dma_client_out = {
. name = " I2S PCM Stereo out "
} ;
static struct s3c2410_dma_client s3c24xx_dma_client_in = {
. name = " I2S PCM Stereo in "
} ;
static struct s3c24xx_pcm_dma_params s3c24xx_i2s_pcm_stereo_out = {
. client = & s3c24xx_dma_client_out ,
. channel = DMACH_I2S_OUT ,
2007-04-17 14:35:48 +04:00
. dma_addr = S3C2410_PA_IIS + S3C2410_IISFIFO ,
. dma_size = 2 ,
2007-02-14 15:17:49 +03:00
} ;
static struct s3c24xx_pcm_dma_params s3c24xx_i2s_pcm_stereo_in = {
. client = & s3c24xx_dma_client_in ,
. channel = DMACH_I2S_IN ,
2007-04-17 14:35:48 +04:00
. dma_addr = S3C2410_PA_IIS + S3C2410_IISFIFO ,
. dma_size = 2 ,
2007-02-14 15:17:49 +03:00
} ;
struct s3c24xx_i2s_info {
void __iomem * regs ;
struct clk * iis_clk ;
2008-01-10 16:44:58 +03:00
u32 iiscon ;
u32 iismod ;
u32 iisfcon ;
u32 iispsr ;
2007-02-14 15:17:49 +03:00
} ;
static struct s3c24xx_i2s_info s3c24xx_i2s ;
static void s3c24xx_snd_txctrl ( int on )
{
u32 iisfcon ;
u32 iiscon ;
u32 iismod ;
2009-03-06 21:04:34 +03:00
pr_debug ( " Entered %s \n " , __func__ ) ;
2007-02-14 15:17:49 +03:00
iisfcon = readl ( s3c24xx_i2s . regs + S3C2410_IISFCON ) ;
iiscon = readl ( s3c24xx_i2s . regs + S3C2410_IISCON ) ;
iismod = readl ( s3c24xx_i2s . regs + S3C2410_IISMOD ) ;
2009-03-11 19:28:29 +03:00
pr_debug ( " r: IISCON: %x IISMOD: %x IISFCON: %x \n " , iiscon , iismod , iisfcon ) ;
2007-02-14 15:17:49 +03:00
if ( on ) {
iisfcon | = S3C2410_IISFCON_TXDMA | S3C2410_IISFCON_TXENABLE ;
iiscon | = S3C2410_IISCON_TXDMAEN | S3C2410_IISCON_IISEN ;
iiscon & = ~ S3C2410_IISCON_TXIDLE ;
iismod | = S3C2410_IISMOD_TXMODE ;
writel ( iismod , s3c24xx_i2s . regs + S3C2410_IISMOD ) ;
writel ( iisfcon , s3c24xx_i2s . regs + S3C2410_IISFCON ) ;
writel ( iiscon , s3c24xx_i2s . regs + S3C2410_IISCON ) ;
} else {
/* note, we have to disable the FIFOs otherwise bad things
* seem to happen when the DMA stops . According to the
* Samsung supplied kernel , this should allow the DMA
* engine and FIFOs to reset . If this isn ' t allowed , the
* DMA engine will simply freeze randomly .
*/
iisfcon & = ~ S3C2410_IISFCON_TXENABLE ;
iisfcon & = ~ S3C2410_IISFCON_TXDMA ;
iiscon | = S3C2410_IISCON_TXIDLE ;
iiscon & = ~ S3C2410_IISCON_TXDMAEN ;
iismod & = ~ S3C2410_IISMOD_TXMODE ;
writel ( iiscon , s3c24xx_i2s . regs + S3C2410_IISCON ) ;
writel ( iisfcon , s3c24xx_i2s . regs + S3C2410_IISFCON ) ;
writel ( iismod , s3c24xx_i2s . regs + S3C2410_IISMOD ) ;
}
2009-03-11 19:28:29 +03:00
pr_debug ( " w: IISCON: %x IISMOD: %x IISFCON: %x \n " , iiscon , iismod , iisfcon ) ;
2007-02-14 15:17:49 +03:00
}
static void s3c24xx_snd_rxctrl ( int on )
{
u32 iisfcon ;
u32 iiscon ;
u32 iismod ;
2009-03-06 21:04:34 +03:00
pr_debug ( " Entered %s \n " , __func__ ) ;
2007-02-14 15:17:49 +03:00
iisfcon = readl ( s3c24xx_i2s . regs + S3C2410_IISFCON ) ;
iiscon = readl ( s3c24xx_i2s . regs + S3C2410_IISCON ) ;
iismod = readl ( s3c24xx_i2s . regs + S3C2410_IISMOD ) ;
2009-03-11 19:28:29 +03:00
pr_debug ( " r: IISCON: %x IISMOD: %x IISFCON: %x \n " , iiscon , iismod , iisfcon ) ;
2007-02-14 15:17:49 +03:00
if ( on ) {
iisfcon | = S3C2410_IISFCON_RXDMA | S3C2410_IISFCON_RXENABLE ;
iiscon | = S3C2410_IISCON_RXDMAEN | S3C2410_IISCON_IISEN ;
iiscon & = ~ S3C2410_IISCON_RXIDLE ;
iismod | = S3C2410_IISMOD_RXMODE ;
writel ( iismod , s3c24xx_i2s . regs + S3C2410_IISMOD ) ;
writel ( iisfcon , s3c24xx_i2s . regs + S3C2410_IISFCON ) ;
writel ( iiscon , s3c24xx_i2s . regs + S3C2410_IISCON ) ;
} else {
/* note, we have to disable the FIFOs otherwise bad things
* seem to happen when the DMA stops . According to the
* Samsung supplied kernel , this should allow the DMA
* engine and FIFOs to reset . If this isn ' t allowed , the
* DMA engine will simply freeze randomly .
*/
2008-04-23 17:09:57 +04:00
iisfcon & = ~ S3C2410_IISFCON_RXENABLE ;
iisfcon & = ~ S3C2410_IISFCON_RXDMA ;
iiscon | = S3C2410_IISCON_RXIDLE ;
iiscon & = ~ S3C2410_IISCON_RXDMAEN ;
2007-02-14 15:17:49 +03:00
iismod & = ~ S3C2410_IISMOD_RXMODE ;
writel ( iisfcon , s3c24xx_i2s . regs + S3C2410_IISFCON ) ;
writel ( iiscon , s3c24xx_i2s . regs + S3C2410_IISCON ) ;
writel ( iismod , s3c24xx_i2s . regs + S3C2410_IISMOD ) ;
}
2009-03-11 19:28:29 +03:00
pr_debug ( " w: IISCON: %x IISMOD: %x IISFCON: %x \n " , iiscon , iismod , iisfcon ) ;
2007-02-14 15:17:49 +03:00
}
/*
* Wait for the LR signal to allow synchronisation to the L / R clock
* from the codec . May only be needed for slave mode .
*/
static int s3c24xx_snd_lrsync ( void )
{
u32 iiscon ;
2008-04-14 16:26:44 +04:00
int timeout = 50 ; /* 5ms */
2007-02-14 15:17:49 +03:00
2009-03-06 21:04:34 +03:00
pr_debug ( " Entered %s \n " , __func__ ) ;
2007-02-14 15:17:49 +03:00
while ( 1 ) {
iiscon = readl ( s3c24xx_i2s . regs + S3C2410_IISCON ) ;
if ( iiscon & S3C2410_IISCON_LRINDEX )
break ;
2008-04-14 16:26:44 +04:00
if ( ! timeout - - )
2007-02-14 15:17:49 +03:00
return - ETIMEDOUT ;
2008-04-14 16:26:44 +04:00
udelay ( 100 ) ;
2007-02-14 15:17:49 +03:00
}
return 0 ;
}
/*
* Check whether CPU is the master or slave
*/
static inline int s3c24xx_snd_is_clkmaster ( void )
{
2009-03-06 21:04:34 +03:00
pr_debug ( " Entered %s \n " , __func__ ) ;
2007-02-14 15:17:49 +03:00
return ( readl ( s3c24xx_i2s . regs + S3C2410_IISMOD ) & S3C2410_IISMOD_SLAVE ) ? 0 : 1 ;
}
/*
* Set S3C24xx I2S DAI format
*/
2008-07-07 19:08:24 +04:00
static int s3c24xx_i2s_set_fmt ( struct snd_soc_dai * cpu_dai ,
2007-02-14 15:17:49 +03:00
unsigned int fmt )
{
u32 iismod ;
2009-03-06 21:04:34 +03:00
pr_debug ( " Entered %s \n " , __func__ ) ;
2007-02-14 15:17:49 +03:00
iismod = readl ( s3c24xx_i2s . regs + S3C2410_IISMOD ) ;
2009-03-11 19:28:29 +03:00
pr_debug ( " hw_params r: IISMOD: %x \n " , iismod ) ;
2007-02-14 15:17:49 +03:00
switch ( fmt & SND_SOC_DAIFMT_MASTER_MASK ) {
case SND_SOC_DAIFMT_CBM_CFM :
iismod | = S3C2410_IISMOD_SLAVE ;
break ;
case SND_SOC_DAIFMT_CBS_CFS :
2008-05-05 16:59:39 +04:00
iismod & = ~ S3C2410_IISMOD_SLAVE ;
2007-02-14 15:17:49 +03:00
break ;
default :
return - EINVAL ;
}
switch ( fmt & SND_SOC_DAIFMT_FORMAT_MASK ) {
case SND_SOC_DAIFMT_LEFT_J :
iismod | = S3C2410_IISMOD_MSB ;
break ;
case SND_SOC_DAIFMT_I2S :
2008-05-05 16:59:39 +04:00
iismod & = ~ S3C2410_IISMOD_MSB ;
2007-02-14 15:17:49 +03:00
break ;
default :
return - EINVAL ;
}
writel ( iismod , s3c24xx_i2s . regs + S3C2410_IISMOD ) ;
2009-03-11 19:28:29 +03:00
pr_debug ( " hw_params w: IISMOD: %x \n " , iismod ) ;
2007-02-14 15:17:49 +03:00
return 0 ;
}
static int s3c24xx_i2s_hw_params ( struct snd_pcm_substream * substream ,
2008-11-19 01:11:38 +03:00
struct snd_pcm_hw_params * params ,
struct snd_soc_dai * dai )
2007-02-14 15:17:49 +03:00
{
struct snd_soc_pcm_runtime * rtd = substream - > private_data ;
u32 iismod ;
2009-03-06 21:04:34 +03:00
pr_debug ( " Entered %s \n " , __func__ ) ;
2007-02-14 15:17:49 +03:00
if ( substream - > stream = = SNDRV_PCM_STREAM_PLAYBACK )
rtd - > dai - > cpu_dai - > dma_data = & s3c24xx_i2s_pcm_stereo_out ;
else
rtd - > dai - > cpu_dai - > dma_data = & s3c24xx_i2s_pcm_stereo_in ;
/* Working copies of register */
iismod = readl ( s3c24xx_i2s . regs + S3C2410_IISMOD ) ;
2009-03-11 19:28:29 +03:00
pr_debug ( " hw_params r: IISMOD: %x \n " , iismod ) ;
2007-02-14 15:17:49 +03:00
switch ( params_format ( params ) ) {
case SNDRV_PCM_FORMAT_S8 :
2008-11-08 10:44:16 +03:00
iismod & = ~ S3C2410_IISMOD_16BIT ;
( ( struct s3c24xx_pcm_dma_params * )
rtd - > dai - > cpu_dai - > dma_data ) - > dma_size = 1 ;
2007-02-14 15:17:49 +03:00
break ;
case SNDRV_PCM_FORMAT_S16_LE :
iismod | = S3C2410_IISMOD_16BIT ;
2008-11-08 10:44:16 +03:00
( ( struct s3c24xx_pcm_dma_params * )
rtd - > dai - > cpu_dai - > dma_data ) - > dma_size = 2 ;
2007-02-14 15:17:49 +03:00
break ;
2008-11-08 10:44:16 +03:00
default :
return - EINVAL ;
2007-02-14 15:17:49 +03:00
}
writel ( iismod , s3c24xx_i2s . regs + S3C2410_IISMOD ) ;
2009-03-11 19:28:29 +03:00
pr_debug ( " hw_params w: IISMOD: %x \n " , iismod ) ;
2007-02-14 15:17:49 +03:00
return 0 ;
}
2008-11-19 01:11:38 +03:00
static int s3c24xx_i2s_trigger ( struct snd_pcm_substream * substream , int cmd ,
struct snd_soc_dai * dai )
2007-02-14 15:17:49 +03:00
{
int ret = 0 ;
2009-03-06 21:04:34 +03:00
pr_debug ( " Entered %s \n " , __func__ ) ;
2007-02-14 15:17:49 +03:00
switch ( cmd ) {
case SNDRV_PCM_TRIGGER_START :
case SNDRV_PCM_TRIGGER_RESUME :
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE :
if ( ! s3c24xx_snd_is_clkmaster ( ) ) {
ret = s3c24xx_snd_lrsync ( ) ;
if ( ret )
goto exit_err ;
}
if ( substream - > stream = = SNDRV_PCM_STREAM_CAPTURE )
s3c24xx_snd_rxctrl ( 1 ) ;
else
s3c24xx_snd_txctrl ( 1 ) ;
break ;
case SNDRV_PCM_TRIGGER_STOP :
case SNDRV_PCM_TRIGGER_SUSPEND :
case SNDRV_PCM_TRIGGER_PAUSE_PUSH :
if ( substream - > stream = = SNDRV_PCM_STREAM_CAPTURE )
s3c24xx_snd_rxctrl ( 0 ) ;
else
s3c24xx_snd_txctrl ( 0 ) ;
break ;
default :
ret = - EINVAL ;
break ;
}
exit_err :
return ret ;
}
/*
* Set S3C24xx Clock source
*/
2008-07-07 19:08:24 +04:00
static int s3c24xx_i2s_set_sysclk ( struct snd_soc_dai * cpu_dai ,
2007-02-14 15:17:49 +03:00
int clk_id , unsigned int freq , int dir )
{
u32 iismod = readl ( s3c24xx_i2s . regs + S3C2410_IISMOD ) ;
2009-03-06 21:04:34 +03:00
pr_debug ( " Entered %s \n " , __func__ ) ;
2007-02-14 15:17:49 +03:00
iismod & = ~ S3C2440_IISMOD_MPLL ;
switch ( clk_id ) {
case S3C24XX_CLKSRC_PCLK :
break ;
case S3C24XX_CLKSRC_MPLL :
iismod | = S3C2440_IISMOD_MPLL ;
break ;
default :
return - EINVAL ;
}
writel ( iismod , s3c24xx_i2s . regs + S3C2410_IISMOD ) ;
return 0 ;
}
/*
* Set S3C24xx Clock dividers
*/
2008-07-07 19:08:24 +04:00
static int s3c24xx_i2s_set_clkdiv ( struct snd_soc_dai * cpu_dai ,
2007-02-14 15:17:49 +03:00
int div_id , int div )
{
u32 reg ;
2009-03-06 21:04:34 +03:00
pr_debug ( " Entered %s \n " , __func__ ) ;
2007-02-14 15:17:49 +03:00
switch ( div_id ) {
2007-07-12 14:27:24 +04:00
case S3C24XX_DIV_BCLK :
2007-02-14 15:17:49 +03:00
reg = readl ( s3c24xx_i2s . regs + S3C2410_IISMOD ) & ~ S3C2410_IISMOD_FS_MASK ;
writel ( reg | div , s3c24xx_i2s . regs + S3C2410_IISMOD ) ;
break ;
2007-07-12 14:27:24 +04:00
case S3C24XX_DIV_MCLK :
2007-02-14 15:17:49 +03:00
reg = readl ( s3c24xx_i2s . regs + S3C2410_IISMOD ) & ~ ( S3C2410_IISMOD_384FS ) ;
writel ( reg | div , s3c24xx_i2s . regs + S3C2410_IISMOD ) ;
break ;
case S3C24XX_DIV_PRESCALER :
writel ( div , s3c24xx_i2s . regs + S3C2410_IISPSR ) ;
reg = readl ( s3c24xx_i2s . regs + S3C2410_IISCON ) ;
writel ( reg | S3C2410_IISCON_PSCEN , s3c24xx_i2s . regs + S3C2410_IISCON ) ;
break ;
default :
return - EINVAL ;
}
return 0 ;
}
/*
* To avoid duplicating clock code , allow machine driver to
* get the clockrate from here .
*/
u32 s3c24xx_i2s_get_clockrate ( void )
{
return clk_get_rate ( s3c24xx_i2s . iis_clk ) ;
}
EXPORT_SYMBOL_GPL ( s3c24xx_i2s_get_clockrate ) ;
2008-06-11 16:47:10 +04:00
static int s3c24xx_i2s_probe ( struct platform_device * pdev ,
2008-07-07 19:08:24 +04:00
struct snd_soc_dai * dai )
2007-02-14 15:17:49 +03:00
{
2009-03-06 21:04:34 +03:00
pr_debug ( " Entered %s \n " , __func__ ) ;
2007-02-14 15:17:49 +03:00
s3c24xx_i2s . regs = ioremap ( S3C2410_PA_IIS , 0x100 ) ;
if ( s3c24xx_i2s . regs = = NULL )
return - ENXIO ;
2008-04-23 17:10:28 +04:00
s3c24xx_i2s . iis_clk = clk_get ( & pdev - > dev , " iis " ) ;
2007-02-14 15:17:49 +03:00
if ( s3c24xx_i2s . iis_clk = = NULL ) {
2009-03-06 21:13:43 +03:00
pr_err ( " failed to get iis_clock \n " ) ;
2007-08-01 15:38:59 +04:00
iounmap ( s3c24xx_i2s . regs ) ;
2007-02-14 15:17:49 +03:00
return - ENODEV ;
}
clk_enable ( s3c24xx_i2s . iis_clk ) ;
/* 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 ) ;
writel ( S3C2410_IISCON_IISEN , s3c24xx_i2s . regs + S3C2410_IISCON ) ;
s3c24xx_snd_txctrl ( 0 ) ;
s3c24xx_snd_rxctrl ( 0 ) ;
return 0 ;
}
2008-01-10 16:44:58 +03:00
# ifdef CONFIG_PM
2008-12-03 21:21:52 +03:00
static int s3c24xx_i2s_suspend ( struct snd_soc_dai * cpu_dai )
2008-01-10 16:44:58 +03:00
{
2009-03-06 21:04:34 +03:00
pr_debug ( " Entered %s \n " , __func__ ) ;
2008-04-22 20:26:59 +04:00
2008-01-10 16:44:58 +03:00
s3c24xx_i2s . iiscon = readl ( s3c24xx_i2s . regs + S3C2410_IISCON ) ;
s3c24xx_i2s . iismod = readl ( s3c24xx_i2s . regs + S3C2410_IISMOD ) ;
s3c24xx_i2s . iisfcon = readl ( s3c24xx_i2s . regs + S3C2410_IISFCON ) ;
s3c24xx_i2s . iispsr = readl ( s3c24xx_i2s . regs + S3C2410_IISPSR ) ;
clk_disable ( s3c24xx_i2s . iis_clk ) ;
return 0 ;
}
2008-12-03 21:21:52 +03:00
static int s3c24xx_i2s_resume ( struct snd_soc_dai * cpu_dai )
2008-01-10 16:44:58 +03:00
{
2009-03-06 21:04:34 +03:00
pr_debug ( " Entered %s \n " , __func__ ) ;
2008-01-10 16:44:58 +03:00
clk_enable ( s3c24xx_i2s . iis_clk ) ;
writel ( s3c24xx_i2s . iiscon , s3c24xx_i2s . regs + S3C2410_IISCON ) ;
writel ( s3c24xx_i2s . iismod , s3c24xx_i2s . regs + S3C2410_IISMOD ) ;
writel ( s3c24xx_i2s . iisfcon , s3c24xx_i2s . regs + S3C2410_IISFCON ) ;
writel ( s3c24xx_i2s . iispsr , s3c24xx_i2s . regs + S3C2410_IISPSR ) ;
return 0 ;
}
# else
# define s3c24xx_i2s_suspend NULL
# define s3c24xx_i2s_resume NULL
# endif
2007-02-14 15:17:49 +03:00
# define S3C24XX_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 04:41:00 +03:00
static struct snd_soc_dai_ops s3c24xx_i2s_dai_ops = {
. trigger = s3c24xx_i2s_trigger ,
. hw_params = s3c24xx_i2s_hw_params ,
. set_fmt = s3c24xx_i2s_set_fmt ,
. set_clkdiv = s3c24xx_i2s_set_clkdiv ,
. set_sysclk = s3c24xx_i2s_set_sysclk ,
} ;
2008-07-07 19:08:24 +04:00
struct snd_soc_dai s3c24xx_i2s_dai = {
2007-02-14 15:17:49 +03:00
. name = " s3c24xx-i2s " ,
. id = 0 ,
. probe = s3c24xx_i2s_probe ,
2008-01-10 16:44:58 +03:00
. suspend = s3c24xx_i2s_suspend ,
. resume = s3c24xx_i2s_resume ,
2007-02-14 15:17:49 +03:00
. playback = {
. channels_min = 2 ,
. channels_max = 2 ,
. rates = S3C24XX_I2S_RATES ,
. formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE , } ,
. capture = {
. channels_min = 2 ,
. channels_max = 2 ,
. rates = S3C24XX_I2S_RATES ,
. formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE , } ,
2009-03-03 04:41:00 +03:00
. ops = & s3c24xx_i2s_dai_ops ,
2007-02-14 15:17:49 +03:00
} ;
EXPORT_SYMBOL_GPL ( s3c24xx_i2s_dai ) ;
2008-12-10 09:47:22 +03:00
static int __init s3c24xx_i2s_init ( void )
2008-12-03 22:26:35 +03:00
{
return snd_soc_register_dai ( & s3c24xx_i2s_dai ) ;
}
module_init ( s3c24xx_i2s_init ) ;
static void __exit s3c24xx_i2s_exit ( void )
{
snd_soc_unregister_dai ( & s3c24xx_i2s_dai ) ;
}
module_exit ( s3c24xx_i2s_exit ) ;
2007-02-14 15:17:49 +03:00
/* Module information */
MODULE_AUTHOR ( " Ben Dooks, <ben@simtec.co.uk> " ) ;
MODULE_DESCRIPTION ( " s3c24xx I2S SoC Interface " ) ;
MODULE_LICENSE ( " GPL " ) ;