2019-04-19 13:21:49 +03:00
// SPDX-License-Identifier: GPL-2.0+
//
// s3c24xx-i2s.c -- ALSA Soc Audio Layer
//
// (c) 2006 Wolfson Microelectronics PLC.
// Graeme Gregory graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com
//
// Copyright 2004-2005 Simtec Electronics
// http://armlinux.simtec.co.uk/
// Ben Dooks <ben@simtec.co.uk>
2007-02-14 15:17:49 +03:00
# include <linux/delay.h>
# include <linux/clk.h>
2008-04-23 17:09:31 +04:00
# include <linux/io.h>
2009-05-14 01:52:24 +04:00
# include <linux/gpio.h>
2011-07-15 20:38:28 +04:00
# include <linux/module.h>
2009-05-14 01:52:24 +04:00
2007-02-14 15:17:49 +03:00
# include <sound/soc.h>
2011-01-11 01:26:06 +03:00
# include <sound/pcm_params.h>
2007-02-14 15:17:49 +03:00
2013-04-11 21:08:42 +04:00
# include "regs-iis.h"
2010-11-22 09:35:57 +03:00
# include "dma.h"
2007-02-14 15:17:49 +03:00
# include "s3c24xx-i2s.h"
2016-08-04 12:30:27 +03:00
static struct snd_dmaengine_dai_dma_data s3c24xx_i2s_pcm_stereo_out = {
2017-01-17 16:16:42 +03:00
. chan_name = " tx " ,
2016-08-04 12:30:27 +03:00
. addr_width = 2 ,
2007-02-14 15:17:49 +03:00
} ;
2016-08-04 12:30:27 +03:00
static struct snd_dmaengine_dai_dma_data s3c24xx_i2s_pcm_stereo_in = {
2017-01-17 16:16:42 +03:00
. chan_name = " rx " ,
2016-08-04 12:30:27 +03:00
. addr_width = 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 ;
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 ;
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
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 )
{
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 ;
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 ) ;
2016-10-25 18:08:41 +03:00
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
{
2014-06-24 00:24:04 +04:00
struct snd_dmaengine_dai_dma_data * dma_data ;
2007-02-14 15:17:49 +03:00
u32 iismod ;
2014-06-24 00:24:04 +04:00
dma_data = snd_soc_dai_get_dma_data ( dai , substream ) ;
2007-02-14 15:17:49 +03:00
/* 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
2014-05-23 16:05:39 +04:00
switch ( params_width ( params ) ) {
case 8 :
2008-11-08 10:44:16 +03:00
iismod & = ~ S3C2410_IISMOD_16BIT ;
2014-06-24 00:24:04 +04:00
dma_data - > addr_width = 1 ;
2007-02-14 15:17:49 +03:00
break ;
2014-05-23 16:05:39 +04:00
case 16 :
2007-02-14 15:17:49 +03:00
iismod | = S3C2410_IISMOD_16BIT ;
2014-06-24 00:24:04 +04:00
dma_data - > addr_width = 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 ) ;
2016-10-25 18:08:41 +03:00
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 ;
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 16:05:50 +04:00
2007-02-14 15:17:49 +03: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 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 ) ;
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 ;
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 ) ;
2010-03-17 23:15:21 +03:00
static int s3c24xx_i2s_probe ( struct snd_soc_dai * dai )
2007-02-14 15:17:49 +03:00
{
2017-07-25 13:14:29 +03:00
int ret ;
2016-08-04 12:30:27 +03:00
snd_soc_dai_init_dma_data ( dai , & s3c24xx_i2s_pcm_stereo_out ,
& s3c24xx_i2s_pcm_stereo_in ) ;
2007-02-14 15:17:49 +03:00
2014-06-24 00:24:04 +04:00
s3c24xx_i2s . iis_clk = devm_clk_get ( dai - > dev , " iis " ) ;
2011-09-15 06:36:54 +04:00
if ( IS_ERR ( s3c24xx_i2s . iis_clk ) ) {
2009-03-06 21:13:43 +03:00
pr_err ( " failed to get iis_clock \n " ) ;
2011-09-15 06:36:54 +04:00
return PTR_ERR ( s3c24xx_i2s . iis_clk ) ;
2007-02-14 15:17:49 +03:00
}
2017-07-25 13:14:29 +03:00
ret = clk_prepare_enable ( s3c24xx_i2s . iis_clk ) ;
if ( ret )
return ret ;
2007-02-14 15:17:49 +03:00
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
2020-01-20 04:04:07 +03:00
static int s3c24xx_i2s_suspend ( struct snd_soc_component * component )
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 ) ;
2014-06-24 00:24:07 +04:00
clk_disable_unprepare ( s3c24xx_i2s . iis_clk ) ;
2008-01-10 16:44:58 +03:00
return 0 ;
}
2020-01-20 04:04:07 +03:00
static int s3c24xx_i2s_resume ( struct snd_soc_component * component )
2008-01-10 16:44:58 +03:00
{
2017-07-25 13:14:29 +03:00
int ret ;
ret = clk_prepare_enable ( s3c24xx_i2s . iis_clk ) ;
if ( ret )
return ret ;
2008-01-10 16:44:58 +03: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 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 )
2011-11-23 14:40:40 +04:00
static const struct snd_soc_dai_ops s3c24xx_i2s_dai_ops = {
2009-03-03 04:41:00 +03: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 23:15:21 +03:00
static struct snd_soc_dai_driver s3c24xx_i2s_dai = {
2007-02-14 15:17:49 +03:00
. probe = s3c24xx_i2s_probe ,
. 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
} ;
2010-03-17 23:15:21 +03:00
2013-03-21 14:35:11 +04:00
static const struct snd_soc_component_driver s3c24xx_i2s_component = {
. name = " s3c24xx-i2s " ,
2020-01-20 04:04:07 +03:00
. suspend = s3c24xx_i2s_suspend ,
. resume = s3c24xx_i2s_resume ,
2013-03-21 14:35:11 +04:00
} ;
2012-12-07 18:26:15 +04:00
static int s3c24xx_iis_dev_probe ( struct platform_device * pdev )
2010-03-17 23:15:21 +03:00
{
2014-06-24 00:24:04 +04:00
struct resource * res ;
2016-11-02 14:11:47 +03:00
int ret ;
2014-06-24 00:24:04 +04:00
2021-06-16 12:16:52 +03:00
s3c24xx_i2s . regs = devm_platform_get_and_ioremap_resource ( pdev , 0 , & res ) ;
2015-04-16 15:18:02 +03:00
if ( IS_ERR ( s3c24xx_i2s . regs ) )
return PTR_ERR ( s3c24xx_i2s . regs ) ;
2014-06-24 00:24:04 +04:00
2016-08-04 12:30:27 +03:00
s3c24xx_i2s_pcm_stereo_out . addr = res - > start + S3C2410_IISFIFO ;
s3c24xx_i2s_pcm_stereo_in . addr = res - > start + S3C2410_IISFIFO ;
2012-12-07 12:29:21 +04:00
2016-11-02 14:04:36 +03:00
ret = samsung_asoc_dma_platform_register ( & pdev - > dev , NULL ,
2019-02-14 12:37:41 +03:00
" tx " , " rx " , NULL ) ;
2012-12-07 12:29:21 +04:00
if ( ret ) {
2016-11-02 14:04:36 +03:00
dev_err ( & pdev - > dev , " Failed to register the DMA: %d \n " , ret ) ;
2012-12-07 12:29:21 +04:00
return ret ;
}
2016-10-27 13:34:02 +03:00
ret = devm_snd_soc_register_component ( & pdev - > dev ,
& s3c24xx_i2s_component , & s3c24xx_i2s_dai , 1 ) ;
2014-05-21 07:22:19 +04:00
if ( ret )
2016-11-02 14:04:36 +03:00
dev_err ( & pdev - > dev , " Failed to register the DAI \n " ) ;
2012-12-07 12:29:21 +04:00
return ret ;
2010-03-17 23:15:21 +03:00
}
static struct platform_driver s3c24xx_iis_driver = {
. probe = s3c24xx_iis_dev_probe ,
. driver = {
. name = " s3c24xx-iis " ,
} ,
} ;
2007-02-14 15:17:49 +03:00
2011-11-23 19:20:13 +04:00
module_platform_driver ( s3c24xx_iis_driver ) ;
2008-12-03 22:26:35 +03:00
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 " ) ;
2010-08-12 14:02:19 +04:00
MODULE_ALIAS ( " platform:s3c24xx-iis " ) ;