2007-02-14 13:17:49 +01: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 17:09:57 +00:00
* Copyright 2004 - 2005 Simtec Electronics
2007-02-14 13:17:49 +01: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/delay.h>
# include <linux/clk.h>
2008-04-23 15:09:31 +02:00
# include <linux/io.h>
2009-05-13 22:52:24 +01:00
# include <linux/gpio.h>
2011-07-15 12:38:28 -04:00
# include <linux/module.h>
2009-05-13 22:52:24 +01:00
2007-02-14 13:17:49 +01:00
# include <sound/soc.h>
2011-01-11 07:26:06 +09:00
# include <sound/pcm_params.h>
2007-02-14 13:17:49 +01:00
2014-01-22 17:30:38 +05:30
# include <mach/gpio-samsung.h>
# include <plat/gpio-cfg.h>
2013-04-11 19:08:42 +02:00
# include "regs-iis.h"
2007-12-19 15:37:49 +01:00
2010-11-22 15:35:57 +09:00
# include "dma.h"
2007-02-14 13:17:49 +01:00
# include "s3c24xx-i2s.h"
2016-08-04 11:30:27 +02:00
static struct snd_dmaengine_dai_dma_data s3c24xx_i2s_pcm_stereo_out = {
2017-01-17 14:16:42 +01:00
. chan_name = " tx " ,
2016-08-04 11:30:27 +02:00
. addr_width = 2 ,
2007-02-14 13:17:49 +01:00
} ;
2016-08-04 11:30:27 +02:00
static struct snd_dmaengine_dai_dma_data s3c24xx_i2s_pcm_stereo_in = {
2017-01-17 14:16:42 +01:00
. chan_name = " rx " ,
2016-08-04 11:30:27 +02:00
. addr_width = 2 ,
2007-02-14 13:17:49 +01:00
} ;
struct s3c24xx_i2s_info {
void __iomem * regs ;
struct clk * iis_clk ;
2008-01-10 14:44:58 +01:00
u32 iiscon ;
u32 iismod ;
u32 iisfcon ;
u32 iispsr ;
2007-02-14 13:17:49 +01:00
} ;
static struct s3c24xx_i2s_info s3c24xx_i2s ;
static void s3c24xx_snd_txctrl ( int on )
{
u32 iisfcon ;
u32 iiscon ;
u32 iismod ;
iisfcon = readl ( s3c24xx_i2s . regs + S3C2410_IISFCON ) ;
iiscon = readl ( s3c24xx_i2s . regs + S3C2410_IISCON ) ;
iismod = readl ( s3c24xx_i2s . regs + S3C2410_IISMOD ) ;
2009-03-11 16:28:29 +00:00
pr_debug ( " r: IISCON: %x IISMOD: %x IISFCON: %x \n " , iiscon , iismod , iisfcon ) ;
2007-02-14 13:17:49 +01: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 16:28:29 +00:00
pr_debug ( " w: IISCON: %x IISMOD: %x IISFCON: %x \n " , iiscon , iismod , iisfcon ) ;
2007-02-14 13:17:49 +01:00
}
static void s3c24xx_snd_rxctrl ( int on )
{
u32 iisfcon ;
u32 iiscon ;
u32 iismod ;
iisfcon = readl ( s3c24xx_i2s . regs + S3C2410_IISFCON ) ;
iiscon = readl ( s3c24xx_i2s . regs + S3C2410_IISCON ) ;
iismod = readl ( s3c24xx_i2s . regs + S3C2410_IISMOD ) ;
2009-03-11 16:28:29 +00:00
pr_debug ( " r: IISCON: %x IISMOD: %x IISFCON: %x \n " , iiscon , iismod , iisfcon ) ;
2007-02-14 13:17:49 +01: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 15:09:57 +02:00
iisfcon & = ~ S3C2410_IISFCON_RXENABLE ;
iisfcon & = ~ S3C2410_IISFCON_RXDMA ;
iiscon | = S3C2410_IISCON_RXIDLE ;
iiscon & = ~ S3C2410_IISCON_RXDMAEN ;
2007-02-14 13:17:49 +01: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 16:28:29 +00:00
pr_debug ( " w: IISCON: %x IISMOD: %x IISFCON: %x \n " , iiscon , iismod , iisfcon ) ;
2007-02-14 13:17:49 +01: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 14:26:44 +02:00
int timeout = 50 ; /* 5ms */
2007-02-14 13:17:49 +01:00
while ( 1 ) {
iiscon = readl ( s3c24xx_i2s . regs + S3C2410_IISCON ) ;
if ( iiscon & S3C2410_IISCON_LRINDEX )
break ;
2008-04-14 14:26:44 +02:00
if ( ! timeout - - )
2007-02-14 13:17:49 +01:00
return - ETIMEDOUT ;
2008-04-14 14:26:44 +02:00
udelay ( 100 ) ;
2007-02-14 13:17:49 +01:00
}
return 0 ;
}
/*
* Check whether CPU is the master or slave
*/
static inline int s3c24xx_snd_is_clkmaster ( void )
{
return ( readl ( s3c24xx_i2s . regs + S3C2410_IISMOD ) & S3C2410_IISMOD_SLAVE ) ? 0 : 1 ;
}
/*
* Set S3C24xx I2S DAI format
*/
2008-07-07 16:08:24 +01:00
static int s3c24xx_i2s_set_fmt ( struct snd_soc_dai * cpu_dai ,
2007-02-14 13:17:49 +01:00
unsigned int fmt )
{
u32 iismod ;
iismod = readl ( s3c24xx_i2s . regs + S3C2410_IISMOD ) ;
2009-03-11 16:28:29 +00:00
pr_debug ( " hw_params r: IISMOD: %x \n " , iismod ) ;
2007-02-14 13:17:49 +01: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 14:59:39 +02:00
iismod & = ~ S3C2410_IISMOD_SLAVE ;
2007-02-14 13:17:49 +01: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 14:59:39 +02:00
iismod & = ~ S3C2410_IISMOD_MSB ;
2007-02-14 13:17:49 +01:00
break ;
default :
return - EINVAL ;
}
writel ( iismod , s3c24xx_i2s . regs + S3C2410_IISMOD ) ;
2009-03-11 16:28:29 +00:00
pr_debug ( " hw_params w: IISMOD: %x \n " , iismod ) ;
2016-10-25 17:08:41 +02:00
2007-02-14 13:17:49 +01:00
return 0 ;
}
static int s3c24xx_i2s_hw_params ( struct snd_pcm_substream * substream ,
2008-11-18 22:11:38 +00:00
struct snd_pcm_hw_params * params ,
struct snd_soc_dai * dai )
2007-02-14 13:17:49 +01:00
{
2014-06-23 23:24:04 +03:00
struct snd_dmaengine_dai_dma_data * dma_data ;
2007-02-14 13:17:49 +01:00
u32 iismod ;
2014-06-23 23:24:04 +03:00
dma_data = snd_soc_dai_get_dma_data ( dai , substream ) ;
2007-02-14 13:17:49 +01:00
/* Working copies of register */
iismod = readl ( s3c24xx_i2s . regs + S3C2410_IISMOD ) ;
2009-03-11 16:28:29 +00:00
pr_debug ( " hw_params r: IISMOD: %x \n " , iismod ) ;
2007-02-14 13:17:49 +01:00
2014-05-23 17:35:39 +05:30
switch ( params_width ( params ) ) {
case 8 :
2008-11-08 08:44:16 +01:00
iismod & = ~ S3C2410_IISMOD_16BIT ;
2014-06-23 23:24:04 +03:00
dma_data - > addr_width = 1 ;
2007-02-14 13:17:49 +01:00
break ;
2014-05-23 17:35:39 +05:30
case 16 :
2007-02-14 13:17:49 +01:00
iismod | = S3C2410_IISMOD_16BIT ;
2014-06-23 23:24:04 +03:00
dma_data - > addr_width = 2 ;
2007-02-14 13:17:49 +01:00
break ;
2008-11-08 08:44:16 +01:00
default :
return - EINVAL ;
2007-02-14 13:17:49 +01:00
}
writel ( iismod , s3c24xx_i2s . regs + S3C2410_IISMOD ) ;
2009-03-11 16:28:29 +00:00
pr_debug ( " hw_params w: IISMOD: %x \n " , iismod ) ;
2016-10-25 17:08:41 +02:00
2007-02-14 13:17:49 +01:00
return 0 ;
}
2008-11-18 22:11:38 +00:00
static int s3c24xx_i2s_trigger ( struct snd_pcm_substream * substream , int cmd ,
struct snd_soc_dai * dai )
2007-02-14 13:17:49 +01:00
{
int ret = 0 ;
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 ) ;
ASoC: S3C platform: Fix s3c2410_dma_started() called at improper time
s3c24xx dma has the auto reload feature, when the the trnasfer is done,
CURR_TC(DSTAT[19:0], current value of transfer count) reaches 0, and DMA
ACK becomes 1, and then, TC(DCON[19:0]) will be loaded into CURR_TC. So
the transmission is repeated.
IRQ is issued while auto reload occurs. We change the DISRC and
DCON[19:0] in the ISR, but at this time, the auto reload has been
performed already. The first block is being re-transmitted by the DMA.
So we need rewrite the DISRC and DCON[19:0] for the next block
immediatly after the this block has been started to be transported.
The function s3c2410_dma_started() is for this perpose, which is called
in the form of "s3c2410_dma_ctrl(prtd->params->channel,
S3C2410_DMAOP_STARTED);" in s3c24xx_pcm_trigger().
But it is not correct. DMA transmission won't start until DMA REQ signal
arrived, it is the time s3c24xx_snd_txctrl(1) or s3c24xx_snd_rxctrl(1)
is called in s3c24xx_i2s_trigger().
In the current framework, s3c24xx_pcm_trigger() is always called before
s3c24xx_pcm_trigger(). So the s3c2410_dma_started() should be called in
s3c24xx_pcm_trigger() after s3c24xx_snd_txctrl(1) or
s3c24xx_snd_rxctrl(1) is called in this function.
However, s3c2410_dma_started() is dma related, to call this function we
should provide the channel number, which is given by
substream->runtime->private_data->params->channel. The private_data
points to a struct s3c24xx_runtime_data object, which is define in
s3c24xx_pcm.c, so s3c2410_dma_started() can't be called in s3c24xx_i2s.c
Fix this by moving the call to signal the DMA started to the DAI
drivers.
Signed-off-by: Shine Liu <liuxian@redflag-linux.com>
Signed-off-by: Shine Liu <shinel@foxmail.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
2009-08-25 20:05:50 +08:00
2007-02-14 13:17:49 +01:00
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 16:08:24 +01:00
static int s3c24xx_i2s_set_sysclk ( struct snd_soc_dai * cpu_dai ,
2007-02-14 13:17:49 +01:00
int clk_id , unsigned int freq , int dir )
{
u32 iismod = readl ( s3c24xx_i2s . regs + S3C2410_IISMOD ) ;
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 16:08:24 +01:00
static int s3c24xx_i2s_set_clkdiv ( struct snd_soc_dai * cpu_dai ,
2007-02-14 13:17:49 +01:00
int div_id , int div )
{
u32 reg ;
switch ( div_id ) {
2007-07-12 12:27:24 +02:00
case S3C24XX_DIV_BCLK :
2007-02-14 13:17:49 +01:00
reg = readl ( s3c24xx_i2s . regs + S3C2410_IISMOD ) & ~ S3C2410_IISMOD_FS_MASK ;
writel ( reg | div , s3c24xx_i2s . regs + S3C2410_IISMOD ) ;
break ;
2007-07-12 12:27:24 +02:00
case S3C24XX_DIV_MCLK :
2007-02-14 13:17:49 +01: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 ) ;
2010-03-17 20:15:21 +00:00
static int s3c24xx_i2s_probe ( struct snd_soc_dai * dai )
2007-02-14 13:17:49 +01:00
{
2016-08-04 11:30:27 +02:00
snd_soc_dai_init_dma_data ( dai , & s3c24xx_i2s_pcm_stereo_out ,
& s3c24xx_i2s_pcm_stereo_in ) ;
2007-02-14 13:17:49 +01:00
2014-06-23 23:24:04 +03:00
s3c24xx_i2s . iis_clk = devm_clk_get ( dai - > dev , " iis " ) ;
2011-09-15 10:36:54 +08:00
if ( IS_ERR ( s3c24xx_i2s . iis_clk ) ) {
2009-03-06 18:13:43 +00:00
pr_err ( " failed to get iis_clock \n " ) ;
2011-09-15 10:36:54 +08:00
return PTR_ERR ( s3c24xx_i2s . iis_clk ) ;
2007-02-14 13:17:49 +01:00
}
2014-06-23 23:24:07 +03:00
clk_prepare_enable ( s3c24xx_i2s . iis_clk ) ;
2007-02-14 13:17:49 +01:00
2012-07-13 19:22:44 +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 ) ;
2007-02-14 13:17:49 +01:00
writel ( S3C2410_IISCON_IISEN , s3c24xx_i2s . regs + S3C2410_IISCON ) ;
s3c24xx_snd_txctrl ( 0 ) ;
s3c24xx_snd_rxctrl ( 0 ) ;
return 0 ;
}
2008-01-10 14:44:58 +01:00
# ifdef CONFIG_PM
2008-12-03 18:21:52 +00:00
static int s3c24xx_i2s_suspend ( struct snd_soc_dai * cpu_dai )
2008-01-10 14:44:58 +01: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 ) ;
2014-06-23 23:24:07 +03:00
clk_disable_unprepare ( s3c24xx_i2s . iis_clk ) ;
2008-01-10 14:44:58 +01:00
return 0 ;
}
2008-12-03 18:21:52 +00:00
static int s3c24xx_i2s_resume ( struct snd_soc_dai * cpu_dai )
2008-01-10 14:44:58 +01:00
{
2014-06-23 23:24:07 +03:00
clk_prepare_enable ( s3c24xx_i2s . iis_clk ) ;
2008-01-10 14:44:58 +01:00
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 13:17:49 +01: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 )
2011-11-23 11:40:40 +01:00
static const struct snd_soc_dai_ops s3c24xx_i2s_dai_ops = {
2009-03-03 09:41:00 +08:00
. 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 ,
} ;
2010-03-17 20:15:21 +00:00
static struct snd_soc_dai_driver s3c24xx_i2s_dai = {
2007-02-14 13:17:49 +01:00
. probe = s3c24xx_i2s_probe ,
2008-01-10 14:44:58 +01:00
. suspend = s3c24xx_i2s_suspend ,
. resume = s3c24xx_i2s_resume ,
2007-02-14 13:17:49 +01: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 09:41:00 +08:00
. ops = & s3c24xx_i2s_dai_ops ,
2007-02-14 13:17:49 +01:00
} ;
2010-03-17 20:15:21 +00:00
2013-03-21 03:35:11 -07:00
static const struct snd_soc_component_driver s3c24xx_i2s_component = {
. name = " s3c24xx-i2s " ,
} ;
2012-12-07 09:26:15 -05:00
static int s3c24xx_iis_dev_probe ( struct platform_device * pdev )
2010-03-17 20:15:21 +00:00
{
2014-06-23 23:24:04 +03:00
struct resource * res ;
2016-11-02 12:11:47 +01:00
int ret ;
2014-06-23 23:24:04 +03:00
res = platform_get_resource ( pdev , IORESOURCE_MEM , 0 ) ;
s3c24xx_i2s . regs = devm_ioremap_resource ( & pdev - > dev , res ) ;
2015-04-16 20:18:02 +08:00
if ( IS_ERR ( s3c24xx_i2s . regs ) )
return PTR_ERR ( s3c24xx_i2s . regs ) ;
2014-06-23 23:24:04 +03:00
2016-08-04 11:30:27 +02:00
s3c24xx_i2s_pcm_stereo_out . addr = res - > start + S3C2410_IISFIFO ;
s3c24xx_i2s_pcm_stereo_in . addr = res - > start + S3C2410_IISFIFO ;
2012-12-07 13:59:21 +05:30
2016-11-02 12:04:36 +01:00
ret = samsung_asoc_dma_platform_register ( & pdev - > dev , NULL ,
2016-10-27 12:34:02 +02:00
NULL , NULL ) ;
2012-12-07 13:59:21 +05:30
if ( ret ) {
2016-11-02 12:04:36 +01:00
dev_err ( & pdev - > dev , " Failed to register the DMA: %d \n " , ret ) ;
2012-12-07 13:59:21 +05:30
return ret ;
}
2016-10-27 12:34:02 +02:00
ret = devm_snd_soc_register_component ( & pdev - > dev ,
& s3c24xx_i2s_component , & s3c24xx_i2s_dai , 1 ) ;
2014-05-21 08:52:19 +05:30
if ( ret )
2016-11-02 12:04:36 +01:00
dev_err ( & pdev - > dev , " Failed to register the DAI \n " ) ;
2012-12-07 13:59:21 +05:30
return ret ;
2010-03-17 20:15:21 +00:00
}
static struct platform_driver s3c24xx_iis_driver = {
. probe = s3c24xx_iis_dev_probe ,
. driver = {
. name = " s3c24xx-iis " ,
} ,
} ;
2007-02-14 13:17:49 +01:00
2011-11-23 15:20:13 +00:00
module_platform_driver ( s3c24xx_iis_driver ) ;
2008-12-03 19:26:35 +00:00
2007-02-14 13:17:49 +01:00
/* Module information */
MODULE_AUTHOR ( " Ben Dooks, <ben@simtec.co.uk> " ) ;
MODULE_DESCRIPTION ( " s3c24xx I2S SoC Interface " ) ;
MODULE_LICENSE ( " GPL " ) ;
2010-08-12 11:02:19 +01:00
MODULE_ALIAS ( " platform:s3c24xx-iis " ) ;