Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
9eb8ae72
Commit
9eb8ae72
authored
Apr 23, 2013
by
Mark Brown
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'asoc/topic/dma' into asoc-next
parents
5561f17f
6f1fd93e
Changes
25
Hide whitespace changes
Inline
Side-by-side
Showing
25 changed files
with
605 additions
and
580 deletions
+605
-580
include/sound/dmaengine_pcm.h
include/sound/dmaengine_pcm.h
+69
-1
include/sound/soc.h
include/sound/soc.h
+4
-0
sound/soc/Kconfig
sound/soc/Kconfig
+4
-0
sound/soc/Makefile
sound/soc/Makefile
+4
-0
sound/soc/atmel/atmel-pcm-dma.c
sound/soc/atmel/atmel-pcm-dma.c
+3
-3
sound/soc/cirrus/ep93xx-pcm.c
sound/soc/cirrus/ep93xx-pcm.c
+3
-2
sound/soc/fsl/Kconfig
sound/soc/fsl/Kconfig
+1
-1
sound/soc/fsl/fsl_ssi.c
sound/soc/fsl/fsl_ssi.c
+13
-6
sound/soc/fsl/imx-pcm-dma.c
sound/soc/fsl/imx-pcm-dma.c
+15
-61
sound/soc/fsl/imx-pcm.c
sound/soc/fsl/imx-pcm.c
+5
-1
sound/soc/fsl/imx-pcm.h
sound/soc/fsl/imx-pcm.h
+5
-0
sound/soc/fsl/imx-ssi.c
sound/soc/fsl/imx-ssi.c
+4
-18
sound/soc/mxs/Kconfig
sound/soc/mxs/Kconfig
+1
-1
sound/soc/mxs/mxs-pcm.c
sound/soc/mxs/mxs-pcm.c
+13
-126
sound/soc/mxs/mxs-saif.c
sound/soc/mxs/mxs-saif.c
+2
-1
sound/soc/omap/omap-pcm.c
sound/soc/omap/omap-pcm.c
+4
-3
sound/soc/pxa/mmp-pcm.c
sound/soc/pxa/mmp-pcm.c
+3
-2
sound/soc/soc-core.c
sound/soc/soc-core.c
+62
-23
sound/soc/soc-dmaengine-pcm.c
sound/soc/soc-dmaengine-pcm.c
+59
-23
sound/soc/soc-generic-dmaengine-pcm.c
sound/soc/soc-generic-dmaengine-pcm.c
+300
-0
sound/soc/spear/spear_pcm.c
sound/soc/spear/spear_pcm.c
+3
-2
sound/soc/tegra/Kconfig
sound/soc/tegra/Kconfig
+1
-1
sound/soc/tegra/tegra_pcm.c
sound/soc/tegra/tegra_pcm.c
+9
-162
sound/soc/ux500/Kconfig
sound/soc/ux500/Kconfig
+1
-1
sound/soc/ux500/ux500_pcm.c
sound/soc/ux500/ux500_pcm.c
+17
-142
No files found.
include/sound/dmaengine_pcm.h
View file @
9eb8ae72
...
...
@@ -16,6 +16,7 @@
#define __SOUND_DMAENGINE_PCM_H__
#include <sound/pcm.h>
#include <sound/soc.h>
#include <linux/dmaengine.h>
/**
...
...
@@ -39,9 +40,15 @@ snd_pcm_uframes_t snd_dmaengine_pcm_pointer(struct snd_pcm_substream *substream)
snd_pcm_uframes_t
snd_dmaengine_pcm_pointer_no_residue
(
struct
snd_pcm_substream
*
substream
);
int
snd_dmaengine_pcm_open
(
struct
snd_pcm_substream
*
substream
,
dma_filter_fn
filter_fn
,
void
*
filter_data
);
struct
dma_chan
*
chan
);
int
snd_dmaengine_pcm_close
(
struct
snd_pcm_substream
*
substream
);
int
snd_dmaengine_pcm_open_request_chan
(
struct
snd_pcm_substream
*
substream
,
dma_filter_fn
filter_fn
,
void
*
filter_data
);
int
snd_dmaengine_pcm_close_release_chan
(
struct
snd_pcm_substream
*
substream
);
struct
dma_chan
*
snd_dmaengine_pcm_request_channel
(
dma_filter_fn
filter_fn
,
void
*
filter_data
);
struct
dma_chan
*
snd_dmaengine_pcm_get_chan
(
struct
snd_pcm_substream
*
substream
);
/**
...
...
@@ -68,4 +75,65 @@ void snd_dmaengine_pcm_set_config_from_dai_data(
const
struct
snd_dmaengine_dai_dma_data
*
dma_data
,
struct
dma_slave_config
*
config
);
/*
* Try to request the DMA channel using compat_request_channel or
* compat_filter_fn if it couldn't be requested through devicetree.
*/
#define SND_DMAENGINE_PCM_FLAG_COMPAT BIT(0)
/*
* Don't try to request the DMA channels through devicetree. This flag only
* makes sense if SND_DMAENGINE_PCM_FLAG_COMPAT is set as well.
*/
#define SND_DMAENGINE_PCM_FLAG_NO_DT BIT(1)
/*
* The platforms dmaengine driver does not support reporting the amount of
* bytes that are still left to transfer.
*/
#define SND_DMAENGINE_PCM_FLAG_NO_RESIDUE BIT(2)
/*
* The PCM is half duplex and the DMA channel is shared between capture and
* playback.
*/
#define SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX BIT(3)
/**
* struct snd_dmaengine_pcm_config - Configuration data for dmaengine based PCM
* @prepare_slave_config: Callback used to fill in the DMA slave_config for a
* PCM substream. Will be called from the PCM drivers hwparams callback.
* @compat_request_channel: Callback to request a DMA channel for platforms
* which do not use devicetree.
* @compat_filter_fn: Will be used as the filter function when requesting a
* channel for platforms which do not use devicetree. The filter parameter
* will be the DAI's DMA data.
* @pcm_hardware: snd_pcm_hardware struct to be used for the PCM.
* @prealloc_buffer_size: Size of the preallocated audio buffer.
*
* Note: If both compat_request_channel and compat_filter_fn are set
* compat_request_channel will be used to request the channel and
* compat_filter_fn will be ignored. Otherwise the channel will be requested
* using dma_request_channel with compat_filter_fn as the filter function.
*/
struct
snd_dmaengine_pcm_config
{
int
(
*
prepare_slave_config
)(
struct
snd_pcm_substream
*
substream
,
struct
snd_pcm_hw_params
*
params
,
struct
dma_slave_config
*
slave_config
);
struct
dma_chan
*
(
*
compat_request_channel
)(
struct
snd_soc_pcm_runtime
*
rtd
,
struct
snd_pcm_substream
*
substream
);
dma_filter_fn
compat_filter_fn
;
const
struct
snd_pcm_hardware
*
pcm_hardware
;
unsigned
int
prealloc_buffer_size
;
};
int
snd_dmaengine_pcm_register
(
struct
device
*
dev
,
const
struct
snd_dmaengine_pcm_config
*
config
,
unsigned
int
flags
);
void
snd_dmaengine_pcm_unregister
(
struct
device
*
dev
);
int
snd_dmaengine_pcm_prepare_slave_config
(
struct
snd_pcm_substream
*
substream
,
struct
snd_pcm_hw_params
*
params
,
struct
dma_slave_config
*
slave_config
);
#endif
include/sound/soc.h
View file @
9eb8ae72
...
...
@@ -375,6 +375,10 @@ int snd_soc_poweroff(struct device *dev);
int
snd_soc_register_platform
(
struct
device
*
dev
,
const
struct
snd_soc_platform_driver
*
platform_drv
);
void
snd_soc_unregister_platform
(
struct
device
*
dev
);
int
snd_soc_add_platform
(
struct
device
*
dev
,
struct
snd_soc_platform
*
platform
,
const
struct
snd_soc_platform_driver
*
platform_drv
);
void
snd_soc_remove_platform
(
struct
snd_soc_platform
*
platform
);
struct
snd_soc_platform
*
snd_soc_lookup_platform
(
struct
device
*
dev
);
int
snd_soc_register_codec
(
struct
device
*
dev
,
const
struct
snd_soc_codec_driver
*
codec_drv
,
struct
snd_soc_dai_driver
*
dai_drv
,
int
num_dai
);
...
...
sound/soc/Kconfig
View file @
9eb8ae72
...
...
@@ -29,6 +29,10 @@ config SND_SOC_AC97_BUS
config SND_SOC_DMAENGINE_PCM
bool
config SND_SOC_GENERIC_DMAENGINE_PCM
bool
select SND_SOC_DMAENGINE_PCM
# All the supported SoCs
source "sound/soc/atmel/Kconfig"
source "sound/soc/au1x/Kconfig"
...
...
sound/soc/Makefile
View file @
9eb8ae72
...
...
@@ -5,6 +5,10 @@ ifneq ($(CONFIG_SND_SOC_DMAENGINE_PCM),)
snd-soc-core-objs
+=
soc-dmaengine-pcm.o
endif
ifneq
($(CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM),)
snd-soc-core-objs
+=
soc-generic-dmaengine-pcm.o
endif
obj-$(CONFIG_SND_SOC)
+=
snd-soc-core.o
obj-$(CONFIG_SND_SOC)
+=
codecs/
obj-$(CONFIG_SND_SOC)
+=
generic/
...
...
sound/soc/atmel/atmel-pcm-dma.c
View file @
9eb8ae72
...
...
@@ -155,7 +155,7 @@ static int atmel_pcm_hw_params(struct snd_pcm_substream *substream,
if
(
ssc
->
pdev
)
sdata
=
ssc
->
pdev
->
dev
.
platform_data
;
ret
=
snd_dmaengine_pcm_open
(
substream
,
filter
,
sdata
);
ret
=
snd_dmaengine_pcm_open
_request_chan
(
substream
,
filter
,
sdata
);
if
(
ret
)
{
pr_err
(
"atmel-pcm: dmaengine pcm open failed
\n
"
);
return
-
EINVAL
;
...
...
@@ -171,7 +171,7 @@ static int atmel_pcm_hw_params(struct snd_pcm_substream *substream,
return
0
;
err:
snd_dmaengine_pcm_close
(
substream
);
snd_dmaengine_pcm_close
_release_chan
(
substream
);
return
ret
;
}
...
...
@@ -197,7 +197,7 @@ static int atmel_pcm_open(struct snd_pcm_substream *substream)
static
struct
snd_pcm_ops
atmel_pcm_ops
=
{
.
open
=
atmel_pcm_open
,
.
close
=
snd_dmaengine_pcm_close
,
.
close
=
snd_dmaengine_pcm_close
_release_chan
,
.
ioctl
=
snd_pcm_lib_ioctl
,
.
hw_params
=
atmel_pcm_hw_params
,
.
prepare
=
atmel_pcm_dma_prepare
,
...
...
sound/soc/cirrus/ep93xx-pcm.c
View file @
9eb8ae72
...
...
@@ -69,7 +69,8 @@ static int ep93xx_pcm_open(struct snd_pcm_substream *substream)
snd_soc_set_runtime_hwparams
(
substream
,
&
ep93xx_pcm_hardware
);
return
snd_dmaengine_pcm_open
(
substream
,
ep93xx_pcm_dma_filter
,
return
snd_dmaengine_pcm_open_request_chan
(
substream
,
ep93xx_pcm_dma_filter
,
snd_soc_dai_get_dma_data
(
rtd
->
cpu_dai
,
substream
));
}
...
...
@@ -100,7 +101,7 @@ static int ep93xx_pcm_mmap(struct snd_pcm_substream *substream,
static
struct
snd_pcm_ops
ep93xx_pcm_ops
=
{
.
open
=
ep93xx_pcm_open
,
.
close
=
snd_dmaengine_pcm_close
,
.
close
=
snd_dmaengine_pcm_close
_release_chan
,
.
ioctl
=
snd_pcm_lib_ioctl
,
.
hw_params
=
ep93xx_pcm_hw_params
,
.
hw_free
=
ep93xx_pcm_hw_free
,
...
...
sound/soc/fsl/Kconfig
View file @
9eb8ae72
...
...
@@ -118,7 +118,7 @@ config SND_SOC_IMX_PCM_FIQ
config SND_SOC_IMX_PCM_DMA
bool
select SND_SOC_DMAENGINE_PCM
select SND_SOC_
GENERIC_
DMAENGINE_PCM
select SND_SOC_IMX_PCM
config SND_SOC_IMX_AUDMUX
...
...
sound/soc/fsl/fsl_ssi.c
View file @
9eb8ae72
...
...
@@ -425,12 +425,6 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream,
ssi_private
->
second_stream
=
substream
;
}
if
(
ssi_private
->
ssi_on_imx
)
snd_soc_dai_set_dma_data
(
dai
,
substream
,
(
substream
->
stream
==
SNDRV_PCM_STREAM_PLAYBACK
)
?
&
ssi_private
->
dma_params_tx
:
&
ssi_private
->
dma_params_rx
);
return
0
;
}
...
...
@@ -552,6 +546,18 @@ static void fsl_ssi_shutdown(struct snd_pcm_substream *substream,
}
}
static
int
fsl_ssi_dai_probe
(
struct
snd_soc_dai
*
dai
)
{
struct
fsl_ssi_private
*
ssi_private
=
snd_soc_dai_get_drvdata
(
dai
);
if
(
ssi_private
->
ssi_on_imx
)
{
dai
->
playback_dma_data
=
&
ssi_private
->
dma_params_tx
;
dai
->
capture_dma_data
=
&
ssi_private
->
dma_params_rx
;
}
return
0
;
}
static
const
struct
snd_soc_dai_ops
fsl_ssi_dai_ops
=
{
.
startup
=
fsl_ssi_startup
,
.
hw_params
=
fsl_ssi_hw_params
,
...
...
@@ -561,6 +567,7 @@ static const struct snd_soc_dai_ops fsl_ssi_dai_ops = {
/* Template for the CPU dai driver structure */
static
struct
snd_soc_dai_driver
fsl_ssi_dai_template
=
{
.
probe
=
fsl_ssi_dai_probe
,
.
playback
=
{
/* The SSI does not support monaural audio. */
.
channels_min
=
2
,
...
...
sound/soc/fsl/imx-pcm-dma.c
View file @
9eb8ae72
...
...
@@ -11,22 +11,12 @@
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/dma-mapping.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/dmaengine.h>
#include <linux/types.h>
#include <sound/core.h>
#include <sound/initval.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/dmaengine_pcm.h>
...
...
@@ -44,32 +34,7 @@ static bool filter(struct dma_chan *chan, void *param)
return
true
;
}
static
int
snd_imx_pcm_hw_params
(
struct
snd_pcm_substream
*
substream
,
struct
snd_pcm_hw_params
*
params
)
{
struct
snd_soc_pcm_runtime
*
rtd
=
substream
->
private_data
;
struct
dma_chan
*
chan
=
snd_dmaengine_pcm_get_chan
(
substream
);
struct
dma_slave_config
slave_config
;
int
ret
;
ret
=
snd_hwparams_to_dma_slave_config
(
substream
,
params
,
&
slave_config
);
if
(
ret
)
return
ret
;
snd_dmaengine_pcm_set_config_from_dai_data
(
substream
,
snd_soc_dai_get_dma_data
(
rtd
->
cpu_dai
,
substream
),
&
slave_config
);
ret
=
dmaengine_slave_config
(
chan
,
&
slave_config
);
if
(
ret
)
return
ret
;
snd_pcm_set_runtime_buffer
(
substream
,
&
substream
->
dma_buffer
);
return
0
;
}
static
struct
snd_pcm_hardware
snd_imx_hardware
=
{
static
const
struct
snd_pcm_hardware
imx_pcm_hardware
=
{
.
info
=
SNDRV_PCM_INFO_INTERLEAVED
|
SNDRV_PCM_INFO_BLOCK_TRANSFER
|
SNDRV_PCM_INFO_MMAP
|
...
...
@@ -88,33 +53,22 @@ static struct snd_pcm_hardware snd_imx_hardware = {
.
fifo_size
=
0
,
};
static
int
snd_imx_open
(
struct
snd_pcm_substream
*
substream
)
{
struct
snd_soc_pcm_runtime
*
rtd
=
substream
->
private_data
;
snd_soc_set_runtime_hwparams
(
substream
,
&
snd_imx_hardware
);
return
snd_dmaengine_pcm_open
(
substream
,
filter
,
snd_soc_dai_get_dma_data
(
rtd
->
cpu_dai
,
substream
));
}
static
struct
snd_pcm_ops
imx_pcm_ops
=
{
.
open
=
snd_imx_open
,
.
close
=
snd_dmaengine_pcm_close
,
.
ioctl
=
snd_pcm_lib_ioctl
,
.
hw_params
=
snd_imx_pcm_hw_params
,
.
trigger
=
snd_dmaengine_pcm_trigger
,
.
pointer
=
snd_dmaengine_pcm_pointer_no_residue
,
.
mmap
=
snd_imx_pcm_mmap
,
};
static
struct
snd_soc_platform_driver
imx_soc_platform_mx2
=
{
.
ops
=
&
imx_pcm_ops
,
.
pcm_new
=
imx_pcm_new
,
.
pcm_free
=
imx_pcm_free
,
static
const
struct
snd_dmaengine_pcm_config
imx_dmaengine_pcm_config
=
{
.
pcm_hardware
=
&
imx_pcm_hardware
,
.
prepare_slave_config
=
snd_dmaengine_pcm_prepare_slave_config
,
.
compat_filter_fn
=
filter
,
.
prealloc_buffer_size
=
IMX_SSI_DMABUF_SIZE
,
};
int
imx_pcm_dma_init
(
struct
platform_device
*
pdev
)
{
return
snd_soc_register_platform
(
&
pdev
->
dev
,
&
imx_soc_platform_mx2
);
return
snd_dmaengine_pcm_register
(
&
pdev
->
dev
,
&
imx_dmaengine_pcm_config
,
SND_DMAENGINE_PCM_FLAG_NO_RESIDUE
|
SND_DMAENGINE_PCM_FLAG_NO_DT
|
SND_DMAENGINE_PCM_FLAG_COMPAT
);
}
void
imx_pcm_dma_exit
(
struct
platform_device
*
pdev
)
{
snd_dmaengine_pcm_unregister
(
&
pdev
->
dev
);
}
sound/soc/fsl/imx-pcm.c
View file @
9eb8ae72
...
...
@@ -114,7 +114,11 @@ static int imx_pcm_probe(struct platform_device *pdev)
static
int
imx_pcm_remove
(
struct
platform_device
*
pdev
)
{
snd_soc_unregister_platform
(
&
pdev
->
dev
);
if
(
strcmp
(
pdev
->
id_entry
->
name
,
"imx-fiq-pcm-audio"
)
==
0
)
snd_soc_unregister_platform
(
&
pdev
->
dev
);
else
imx_pcm_dma_exit
(
pdev
);
return
0
;
}
...
...
sound/soc/fsl/imx-pcm.h
View file @
9eb8ae72
...
...
@@ -39,11 +39,16 @@ void imx_pcm_free(struct snd_pcm *pcm);
#ifdef CONFIG_SND_SOC_IMX_PCM_DMA
int
imx_pcm_dma_init
(
struct
platform_device
*
pdev
);
void
imx_pcm_dma_exit
(
struct
platform_device
*
pdev
);
#else
static
inline
int
imx_pcm_dma_init
(
struct
platform_device
*
pdev
)
{
return
-
ENODEV
;
}
static
inline
void
imx_pcm_dma_exit
(
struct
platform_device
*
pdev
)
{
}
#endif
#ifdef CONFIG_SND_SOC_IMX_PCM_FIQ
...
...
sound/soc/fsl/imx-ssi.c
View file @
9eb8ae72
...
...
@@ -232,23 +232,6 @@ static int imx_ssi_set_dai_clkdiv(struct snd_soc_dai *cpu_dai,
return
0
;
}
static
int
imx_ssi_startup
(
struct
snd_pcm_substream
*
substream
,
struct
snd_soc_dai
*
cpu_dai
)
{
struct
imx_ssi
*
ssi
=
snd_soc_dai_get_drvdata
(
cpu_dai
);
struct
snd_dmaengine_dai_dma_data
*
dma_data
;
/* Tx/Rx config */
if
(
substream
->
stream
==
SNDRV_PCM_STREAM_PLAYBACK
)
dma_data
=
&
ssi
->
dma_params_tx
;
else
dma_data
=
&
ssi
->
dma_params_rx
;
snd_soc_dai_set_dma_data
(
cpu_dai
,
substream
,
dma_data
);
return
0
;
}
/*
* Should only be called when port is inactive (i.e. SSIEN = 0),
* although can be called multiple times by upper layers.
...
...
@@ -353,7 +336,6 @@ static int imx_ssi_trigger(struct snd_pcm_substream *substream, int cmd,
}
static
const
struct
snd_soc_dai_ops
imx_ssi_pcm_dai_ops
=
{
.
startup
=
imx_ssi_startup
,
.
hw_params
=
imx_ssi_hw_params
,
.
set_fmt
=
imx_ssi_set_dai_fmt
,
.
set_clkdiv
=
imx_ssi_set_dai_clkdiv
,
...
...
@@ -373,6 +355,10 @@ static int imx_ssi_dai_probe(struct snd_soc_dai *dai)
SSI_SFCSR_RFWM0
(
ssi
->
dma_params_rx
.
maxburst
);
writel
(
val
,
ssi
->
base
+
SSI_SFCSR
);
/* Tx/Rx config */
dai
->
playback_dma_data
=
&
ssi
->
dma_params_tx
;
dai
->
capture_dma_data
=
&
ssi
->
dma_params_rx
;
return
0
;
}
...
...
sound/soc/mxs/Kconfig
View file @
9eb8ae72
menuconfig SND_MXS_SOC
tristate "SoC Audio for Freescale MXS CPUs"
depends on ARCH_MXS
select SND_SOC_DMAENGINE_PCM
select SND_SOC_
GENERIC_
DMAENGINE_PCM
help
Say Y or M if you want to add support for codecs attached to
the MXS SAIF interface.
...
...
sound/soc/mxs/mxs-pcm.c
View file @
9eb8ae72
...
...
@@ -18,32 +18,24 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/dma-mapping.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/dmaengine.h>
#include <sound/core.h>
#include <sound/initval.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/dmaengine_pcm.h>
#include "mxs-pcm.h"
static
struct
snd_pcm_hardware
snd_mxs_hardware
=
{
static
const
struct
snd_pcm_hardware
snd_mxs_hardware
=
{
.
info
=
SNDRV_PCM_INFO_MMAP
|
SNDRV_PCM_INFO_MMAP_VALID
|
SNDRV_PCM_INFO_PAUSE
|
SNDRV_PCM_INFO_RESUME
|
SNDRV_PCM_INFO_INTERLEAVED
,
SNDRV_PCM_INFO_INTERLEAVED
|
SNDRV_PCM_INFO_HALF_DUPLEX
,
.
formats
=
SNDRV_PCM_FMTBIT_S16_LE
|
SNDRV_PCM_FMTBIT_S20_3LE
|
SNDRV_PCM_FMTBIT_S24_LE
,
...
...
@@ -55,7 +47,6 @@ static struct snd_pcm_hardware snd_mxs_hardware = {
.
periods_max
=
52
,
.
buffer_bytes_max
=
64
*
1024
,
.
fifo_size
=
32
,
};
static
bool
filter
(
struct
dma_chan
*
chan
,
void
*
param
)
...
...
@@ -73,129 +64,25 @@ static bool filter(struct dma_chan *chan, void *param)
return
true
;
}
static
int
snd_mxs_pcm_hw_params
(
struct
snd_pcm_substream
*
substream
,
struct
snd_pcm_hw_params
*
params
)
{
snd_pcm_set_runtime_buffer
(
substream
,
&
substream
->
dma_buffer
);
return
0
;
}
static
int
snd_mxs_open
(
struct
snd_pcm_substream
*
substream
)
{
struct
snd_soc_pcm_runtime
*
rtd
=
substream
->
private_data
;
snd_soc_set_runtime_hwparams
(
substream
,
&
snd_mxs_hardware
);
return
snd_dmaengine_pcm_open
(
substream
,
filter
,
snd_soc_dai_get_dma_data
(
rtd
->
cpu_dai
,
substream
));
}
static
int
snd_mxs_pcm_mmap
(
struct
snd_pcm_substream
*
substream
,
struct
vm_area_struct
*
vma
)
{
struct
snd_pcm_runtime
*
runtime
=
substream
->
runtime
;
return
dma_mmap_writecombine
(
substream
->
pcm
->
card
->
dev
,
vma
,
runtime
->
dma_area
,
runtime
->
dma_addr
,
runtime
->
dma_bytes
);
}
static
struct
snd_pcm_ops
mxs_pcm_ops
=
{
.
open
=
snd_mxs_open
,
.
close
=
snd_dmaengine_pcm_close
,
.
ioctl
=
snd_pcm_lib_ioctl
,
.
hw_params
=
snd_mxs_pcm_hw_params
,
.
trigger
=
snd_dmaengine_pcm_trigger
,
.
pointer
=
snd_dmaengine_pcm_pointer_no_residue
,
.
mmap
=
snd_mxs_pcm_mmap
,
};
static
int
mxs_pcm_preallocate_dma_buffer
(
struct
snd_pcm
*
pcm
,
int
stream
)
{
struct
snd_pcm_substream
*
substream
=
pcm
->
streams
[
stream
].
substream
;
struct
snd_dma_buffer
*
buf
=
&
substream
->
dma_buffer
;
size_t
size
=
snd_mxs_hardware
.
buffer_bytes_max
;
buf
->
dev
.
type
=
SNDRV_DMA_TYPE_DEV
;
buf
->
dev
.
dev
=
pcm
->
card
->
dev
;
buf
->
private_data
=
NULL
;
buf
->
area
=
dma_alloc_writecombine
(
pcm
->
card
->
dev
,
size
,
&
buf
->
addr
,
GFP_KERNEL
);
if
(
!
buf
->
area
)
return
-
ENOMEM
;
buf
->
bytes
=
size
;
return
0
;
}
static
u64
mxs_pcm_dmamask
=
DMA_BIT_MASK
(
32
);
static
int
mxs_pcm_new
(
struct
snd_soc_pcm_runtime
*
rtd
)
{
struct
snd_card
*
card
=
rtd
->
card
->
snd_card
;
struct
snd_pcm
*
pcm
=
rtd
->
pcm
;
int
ret
=
0
;
if
(
!
card
->
dev
->
dma_mask
)
card
->
dev
->
dma_mask
=
&
mxs_pcm_dmamask
;
if
(
!
card
->
dev
->
coherent_dma_mask
)
card
->
dev
->
coherent_dma_mask
=
DMA_BIT_MASK
(
32
);
if
(
pcm
->
streams
[
SNDRV_PCM_STREAM_PLAYBACK
].
substream
)
{
ret
=
mxs_pcm_preallocate_dma_buffer
(
pcm
,
SNDRV_PCM_STREAM_PLAYBACK
);
if
(
ret
)
goto
out
;
}
if
(
pcm
->
streams
[
SNDRV_PCM_STREAM_CAPTURE
].
substream
)
{
ret
=
mxs_pcm_preallocate_dma_buffer
(
pcm
,
SNDRV_PCM_STREAM_CAPTURE
);
if
(
ret
)
goto
out
;
}
out:
return
ret
;
}
static
void
mxs_pcm_free
(
struct
snd_pcm
*
pcm
)
{
struct
snd_pcm_substream
*
substream
;
struct
snd_dma_buffer
*
buf
;
int
stream
;
for
(
stream
=
0
;
stream
<
2
;
stream
++
)
{
substream
=
pcm
->
streams
[
stream
].
substream
;
if
(
!
substream
)
continue
;
buf
=
&
substream
->
dma_buffer
;
if
(
!
buf
->
area
)
continue
;
dma_free_writecombine
(
pcm
->
card
->
dev
,
buf
->
bytes
,
buf
->
area
,
buf
->
addr
);
buf
->
area
=
NULL
;
}
}
static
struct
snd_soc_platform_driver
mxs_soc_platform
=
{
.
ops
=
&
mxs_pcm_ops
,
.
pcm_new
=
mxs_pcm_new
,
.
pcm_free
=
mxs_pcm_free
,
static
const
struct
snd_dmaengine_pcm_config
mxs_dmaengine_pcm_config
=
{
.
pcm_hardware
=
&
snd_mxs_hardware
,
.
compat_filter_fn
=
filter
,
.
prealloc_buffer_size
=
64
*
1024
,
};
int
mxs_pcm_platform_register
(
struct
device
*
dev
)
{
return
snd_soc_register_platform
(
dev
,
&
mxs_soc_platform
);
return
snd_dmaengine_pcm_register
(
dev
,
&
mxs_dmaengine_pcm_config
,
SND_DMAENGINE_PCM_FLAG_NO_RESIDUE
|
SND_DMAENGINE_PCM_FLAG_NO_DT
|
SND_DMAENGINE_PCM_FLAG_COMPAT
|
SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX
);
}
EXPORT_SYMBOL_GPL
(
mxs_pcm_platform_register
);
void
mxs_pcm_platform_unregister
(
struct
device
*
dev
)
{
snd_
soc_unregister_platform
(
dev
);
snd_
dmaengine_pcm_unregister
(
dev
);
}
EXPORT_SYMBOL_GPL
(
mxs_pcm_platform_unregister
);
...
...
sound/soc/mxs/mxs-saif.c
View file @
9eb8ae72
...
...
@@ -369,7 +369,6 @@ static int mxs_saif_startup(struct snd_pcm_substream *substream,
struct
snd_soc_dai
*
cpu_dai
)
{
struct
mxs_saif
*
saif
=
snd_soc_dai_get_drvdata
(
cpu_dai
);
snd_soc_dai_set_dma_data
(
cpu_dai
,
substream
,
&
saif
->
dma_param
);
/* clear error status to 0 for each re-open */
saif
->
fifo_underrun
=
0
;
...
...
@@ -605,6 +604,8 @@ static int mxs_saif_dai_probe(struct snd_soc_dai *dai)
struct
mxs_saif
*
saif
=
dev_get_drvdata
(
dai
->
dev
);
snd_soc_dai_set_drvdata
(
dai
,
saif
);
dai
->
playback_dma_data
=
&
saif
->
dma_param
;
dai
->
capture_dma_data
=
&
saif
->
dma_param
;
return
0
;
}
...
...
sound/soc/omap/omap-pcm.c
View file @
9eb8ae72
...
...
@@ -118,8 +118,9 @@ static int omap_pcm_open(struct snd_pcm_substream *substream)
dma_data
=
snd_soc_dai_get_dma_data
(
rtd
->
cpu_dai
,
substream
);
return
snd_dmaengine_pcm_open
(
substream
,
omap_dma_filter_fn
,
dma_data
->
filter_data
);
return
snd_dmaengine_pcm_open_request_chan
(
substream
,
omap_dma_filter_fn
,
dma_data
->
filter_data
);
}
static
int
omap_pcm_mmap
(
struct
snd_pcm_substream
*
substream
,
...
...
@@ -135,7 +136,7 @@ static int omap_pcm_mmap(struct snd_pcm_substream *substream,
static
struct
snd_pcm_ops
omap_pcm_ops
=
{
.
open
=
omap_pcm_open
,
.
close
=
snd_dmaengine_pcm_close
,
.
close
=
snd_dmaengine_pcm_close
_release_chan
,
.
ioctl
=
snd_pcm_lib_ioctl
,
.
hw_params
=
omap_pcm_hw_params
,
.
hw_free
=
omap_pcm_hw_free
,
...
...
sound/soc/pxa/mmp-pcm.c
View file @
9eb8ae72
...
...
@@ -131,7 +131,8 @@ static int mmp_pcm_open(struct snd_pcm_substream *substream)
dma_data
.
dma_res
=
r
;
dma_data
.
ssp_id
=
cpu_dai
->
id
;
return
snd_dmaengine_pcm_open
(
substream
,
filter
,
&
dma_data
);
return
snd_dmaengine_pcm_open_request_chan
(
substream
,
filter
,
&
dma_data
);
}
static
int
mmp_pcm_mmap
(
struct
snd_pcm_substream
*
substream
,
...
...
@@ -148,7 +149,7 @@ static int mmp_pcm_mmap(struct snd_pcm_substream *substream,
struct
snd_pcm_ops
mmp_pcm_ops
=
{
.
open
=
mmp_pcm_open
,
.
close
=
snd_dmaengine_pcm_close
,
.
close
=
snd_dmaengine_pcm_close
_release_chan
,
.
ioctl
=
snd_pcm_lib_ioctl
,
.
hw_params
=
mmp_pcm_hw_params
,
.
trigger
=
snd_dmaengine_pcm_trigger
,
...
...
sound/soc/soc-core.c
View file @
9eb8ae72
...
...
@@ -3900,21 +3900,14 @@ static void snd_soc_unregister_dais(struct device *dev, size_t count)
}
/**
* snd_soc_register_platform - Register a platform with the ASoC core
*
* @platform: platform to register
* snd_soc_add_platform - Add a platform to the ASoC core
* @dev: The parent device for the platform
* @platform: The platform to add
* @platform_driver: The driver for the platform
*/
int
snd_soc_
register_platform
(
struct
device
*
dev
,
int
snd_soc_
add_platform
(
struct
device
*
dev
,
struct
snd_soc_platform
*
platform
,
const
struct
snd_soc_platform_driver
*
platform_drv
)
{
struct
snd_soc_platform
*
platform
;
dev_dbg
(
dev
,
"ASoC: platform register %s
\n
"
,
dev_name
(
dev
));
platform
=
kzalloc
(
sizeof
(
struct
snd_soc_platform
),
GFP_KERNEL
);
if
(
platform
==
NULL
)
return
-
ENOMEM
;
/* create platform component name */
platform
->
name
=
fmt_single_name
(
dev
,
&
platform
->
id
);
if
(
platform
->
name
==
NULL
)
{
...
...
@@ -3937,30 +3930,76 @@ int snd_soc_register_platform(struct device *dev,
return
0
;
}
EXPORT_SYMBOL_GPL
(
snd_soc_
register
_platform
);
EXPORT_SYMBOL_GPL
(
snd_soc_
add
_platform
);
/**
* snd_soc_
unregister_platform - Unregister a platform from
the ASoC core
* snd_soc_
register_platform - Register a platform with
the ASoC core
*
* @platform: platform to
un
register
* @platform: platform to register
*/
void
snd_soc_unregister_platform
(
struct
device
*
dev
)
int
snd_soc_register_platform
(
struct
device
*
dev
,
const
struct
snd_soc_platform_driver
*
platform_drv
)
{
struct
snd_soc_platform
*
platform
;
int
ret
;
list_for_each_entry
(
platform
,
&
platform_list
,
list
)
{
if
(
dev
==
platform
->
dev
)
goto
found
;
}
return
;
dev_dbg
(
dev
,
"ASoC: platform register %s
\n
"
,
dev_name
(
dev
));
found:
platform
=
kzalloc
(
sizeof
(
struct
snd_soc_platform
),
GFP_KERNEL
);
if
(
platform
==
NULL
)
return
-
ENOMEM
;
ret
=
snd_soc_add_platform
(
dev
,
platform
,
platform_drv
);
if
(
ret
)
kfree
(
platform
);
return
ret
;
}
EXPORT_SYMBOL_GPL
(
snd_soc_register_platform
);
/**
* snd_soc_remove_platform - Remove a platform from the ASoC core
* @platform: the platform to remove
*/
void
snd_soc_remove_platform
(
struct
snd_soc_platform
*
platform
)
{
mutex_lock
(
&
client_mutex
);
list_del
(
&
platform
->
list
);
mutex_unlock
(
&
client_mutex
);
dev_dbg
(
dev
,
"ASoC: Unregistered platform '%s'
\n
"
,
platform
->
name
);
dev_dbg
(
platform
->
dev
,
"ASoC: Unregistered platform '%s'
\n
"
,
platform
->
name
);
kfree
(
platform
->
name
);
}
EXPORT_SYMBOL_GPL
(
snd_soc_remove_platform
);
struct
snd_soc_platform
*
snd_soc_lookup_platform
(
struct
device
*
dev
)
{
struct
snd_soc_platform
*
platform
;
list_for_each_entry
(
platform
,
&
platform_list
,
list
)
{
if
(
dev
==
platform
->
dev
)
return
platform
;
}
return
NULL
;
}
EXPORT_SYMBOL_GPL
(
snd_soc_lookup_platform
);
/**
* snd_soc_unregister_platform - Unregister a platform from the ASoC core
*
* @platform: platform to unregister
*/
void
snd_soc_unregister_platform
(
struct
device
*
dev
)
{
struct
snd_soc_platform
*
platform
;
platform
=
snd_soc_lookup_platform
(
dev
);
if
(
!
platform
)
return
;
snd_soc_remove_platform
(
platform
);
kfree
(
platform
);
}
EXPORT_SYMBOL_GPL
(
snd_soc_unregister_platform
);
...
...
sound/soc/soc-dmaengine-pcm.c
View file @
9eb8ae72
...
...
@@ -254,44 +254,48 @@ snd_pcm_uframes_t snd_dmaengine_pcm_pointer(struct snd_pcm_substream *substream)
}
EXPORT_SYMBOL_GPL
(
snd_dmaengine_pcm_pointer
);
static
int
dmaengine_pcm_request_channel
(
struct
dmaengine_pcm_runtime_data
*
prtd
,
dma_filter_fn
filter_fn
,
void
*
filter_data
)
/**
* snd_dmaengine_pcm_request_channel - Request channel for the dmaengine PCM
* @filter_fn: Filter function used to request the DMA channel
* @filter_data: Data passed to the DMA filter function
*
* Returns NULL or the requested DMA channel.
*
* This function request a DMA channel for usage with dmaengine PCM.
*/
struct
dma_chan
*
snd_dmaengine_pcm_request_channel
(
dma_filter_fn
filter_fn
,
void
*
filter_data
)
{
dma_cap_mask_t
mask
;
dma_cap_zero
(
mask
);
dma_cap_set
(
DMA_SLAVE
,
mask
);
dma_cap_set
(
DMA_CYCLIC
,
mask
);
prtd
->
dma_chan
=
dma_request_channel
(
mask
,
filter_fn
,
filter_data
);
if
(
!
prtd
->
dma_chan
)
return
-
ENXIO
;
return
0
;
return
dma_request_channel
(
mask
,
filter_fn
,
filter_data
)
;
}
EXPORT_SYMBOL_GPL
(
snd_dmaengine_pcm_request_channel
);
/**
* snd_dmaengine_pcm_open - Open a dmaengine based PCM substream
* @substream: PCM substream
* @filter_fn: Filter function used to request the DMA channel
* @filter_data: Data passed to the DMA filter function
* @chan: DMA channel to use for data transfers
*
* Returns 0 on success, a negative error code otherwise.
*
* This function will request a DMA channel using the passed filter function and
* data. The function should usually be called from the pcm open callback.
*
* Note that this function will use private_data field of the substream's
* runtime. So it is not availabe to your pcm driver implementation. If you need
* to keep additional data attached to a substream use
* snd_dmaengine_pcm_{set,get}_data.
* The function should usually be called from the pcm open callback. Note that
* this function will use private_data field of the substream's runtime. So it
* is not availabe to your pcm driver implementation.
*/
int
snd_dmaengine_pcm_open
(
struct
snd_pcm_substream
*
substream
,
dma_filter_fn
filter_fn
,
void
*
filter_data
)
struct
dma_chan
*
chan
)
{
struct
dmaengine_pcm_runtime_data
*
prtd
;
int
ret
;
if
(
!
chan
)
return
-
ENXIO
;
ret
=
snd_pcm_hw_constraint_integer
(
substream
->
runtime
,
SNDRV_PCM_HW_PARAM_PERIODS
);
if
(
ret
<
0
)
...
...
@@ -301,11 +305,7 @@ int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream,
if
(
!
prtd
)
return
-
ENOMEM
;
ret
=
dmaengine_pcm_request_channel
(
prtd
,
filter_fn
,
filter_data
);
if
(
ret
<
0
)
{
kfree
(
prtd
);
return
ret
;
}
prtd
->
dma_chan
=
chan
;
substream
->
runtime
->
private_data
=
prtd
;
...
...
@@ -313,6 +313,27 @@ int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream,
}
EXPORT_SYMBOL_GPL
(
snd_dmaengine_pcm_open
);
/**
* snd_dmaengine_pcm_open_request_chan - Open a dmaengine based PCM substream and request channel
* @substream: PCM substream
* @filter_fn: Filter function used to request the DMA channel
* @filter_data: Data passed to the DMA filter function
*
* Returns 0 on success, a negative error code otherwise.
*
* This function will request a DMA channel using the passed filter function and
* data. The function should usually be called from the pcm open callback. Note
* that this function will use private_data field of the substream's runtime. So
* it is not availabe to your pcm driver implementation.
*/
int
snd_dmaengine_pcm_open_request_chan
(
struct
snd_pcm_substream
*
substream
,
dma_filter_fn
filter_fn
,
void
*
filter_data
)
{
return
snd_dmaengine_pcm_open
(
substream
,
snd_dmaengine_pcm_request_channel
(
filter_fn
,
filter_data
));
}
EXPORT_SYMBOL_GPL
(
snd_dmaengine_pcm_open_request_chan
);
/**
* snd_dmaengine_pcm_close - Close a dmaengine based PCM substream
* @substream: PCM substream
...
...
@@ -321,11 +342,26 @@ int snd_dmaengine_pcm_close(struct snd_pcm_substream *substream)
{
struct
dmaengine_pcm_runtime_data
*
prtd
=
substream_to_prtd
(
substream
);
dma_release_channel
(
prtd
->
dma_chan
);
kfree
(
prtd
);
return
0
;
}
EXPORT_SYMBOL_GPL
(
snd_dmaengine_pcm_close
);
/**
* snd_dmaengine_pcm_release_chan_close - Close a dmaengine based PCM substream and release channel
* @substream: PCM substream
*
* Releases the DMA channel associated with the PCM substream.
*/
int
snd_dmaengine_pcm_close_release_chan
(
struct
snd_pcm_substream
*
substream
)
{
struct
dmaengine_pcm_runtime_data
*
prtd
=
substream_to_prtd
(
substream
);
dma_release_channel
(
prtd
->
dma_chan
);
return
snd_dmaengine_pcm_close
(
substream
);
}
EXPORT_SYMBOL_GPL
(
snd_dmaengine_pcm_close_release_chan
);
MODULE_LICENSE
(
"GPL"
);
sound/soc/soc-generic-dmaengine-pcm.c
0 → 100644
View file @
9eb8ae72
/*
* Copyright (C) 2013, Analog Devices Inc.
* Author: Lars-Peter Clausen <lars@metafoo.de>
*
* 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.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/dmaengine.h>
#include <linux/slab.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <linux/dma-mapping.h>
#include <linux/of.h>
#include <sound/dmaengine_pcm.h>
struct
dmaengine_pcm
{
struct
dma_chan
*
chan
[
SNDRV_PCM_STREAM_CAPTURE
+
1
];
const
struct
snd_dmaengine_pcm_config
*
config
;
struct
snd_soc_platform
platform
;
unsigned
int
flags
;
};
static
struct
dmaengine_pcm
*
soc_platform_to_pcm
(
struct
snd_soc_platform
*
p
)
{
return
container_of
(
p
,
struct
dmaengine_pcm
,
platform
);
}
/**
* snd_dmaengine_pcm_prepare_slave_config() - Generic prepare_slave_config callback
* @substream: PCM substream
* @params: hw_params
* @slave_config: DMA slave config to prepare
*
* This function can be used as a generic prepare_slave_config callback for
* platforms which make use of the snd_dmaengine_dai_dma_data struct for their
* DAI DMA data. Internally the function will first call
* snd_hwparams_to_dma_slave_config to fill in the slave config based on the
* hw_params, followed by snd_dmaengine_set_config_from_dai_data to fill in the
* remaining fields based on the DAI DMA data.
*/
int
snd_dmaengine_pcm_prepare_slave_config
(
struct
snd_pcm_substream
*
substream
,
struct
snd_pcm_hw_params
*
params
,
struct
dma_slave_config
*
slave_config
)
{
struct
snd_soc_pcm_runtime
*
rtd
=
substream
->
private_data
;
struct
snd_dmaengine_dai_dma_data
*
dma_data
;
int
ret
;
dma_data
=
snd_soc_dai_get_dma_data
(
rtd
->
cpu_dai
,
substream
);
ret
=
snd_hwparams_to_dma_slave_config
(
substream
,
params
,
slave_config
);
if
(
ret
)
return
ret
;
snd_dmaengine_pcm_set_config_from_dai_data
(
substream
,
dma_data
,
slave_config
);
return
0
;
}
EXPORT_SYMBOL_GPL
(
snd_dmaengine_pcm_prepare_slave_config
);
static
int
dmaengine_pcm_hw_params
(
struct
snd_pcm_substream
*
substream
,
struct
snd_pcm_hw_params
*
params
)
{
struct
snd_soc_pcm_runtime
*
rtd
=
substream
->
private_data
;
struct
dmaengine_pcm
*
pcm
=
soc_platform_to_pcm
(
rtd
->
platform
);
struct
dma_chan
*
chan
=
snd_dmaengine_pcm_get_chan
(
substream
);
struct
dma_slave_config
slave_config
;
int
ret
;
if
(
pcm
->
config
->
prepare_slave_config
)
{
ret
=
pcm
->
config
->
prepare_slave_config
(
substream
,
params
,
&
slave_config
);
if
(
ret
)
return
ret
;
ret
=
dmaengine_slave_config
(
chan
,
&
slave_config
);
if
(
ret
)
return
ret
;
}
return
snd_pcm_lib_malloc_pages
(
substream
,
params_buffer_bytes
(
params
));
}
static
int
dmaengine_pcm_open
(
struct
snd_pcm_substream
*
substream
)
{
struct
snd_soc_pcm_runtime
*
rtd
=
substream
->
private_data
;
struct
dmaengine_pcm
*
pcm
=
soc_platform_to_pcm
(
rtd
->
platform
);
struct
dma_chan
*
chan
=
pcm
->
chan
[
substream
->
stream
];
int
ret
;
ret
=
snd_soc_set_runtime_hwparams
(
substream
,
pcm
->
config
->
pcm_hardware
);
if
(
ret
)
return
ret
;
return
snd_dmaengine_pcm_open
(
substream
,
chan
);
}
static
struct
device
*
dmaengine_dma_dev
(
struct
dmaengine_pcm
*
pcm
,
struct
snd_pcm_substream
*
substream
)
{
if
(
!
pcm
->
chan
[
substream
->
stream
])
return
NULL
;
return
pcm
->
chan
[
substream
->
stream
]
->
device
->
dev
;
}
static
void
dmaengine_pcm_free
(
struct
snd_pcm
*
pcm
)
{
snd_pcm_lib_preallocate_free_for_all
(
pcm
);
}
static
struct
dma_chan
*
dmaengine_pcm_compat_request_channel
(
struct
snd_soc_pcm_runtime
*
rtd
,
struct
snd_pcm_substream
*
substream
)
{
struct
dmaengine_pcm
*
pcm
=
soc_platform_to_pcm
(
rtd
->
platform
);
if
((
pcm
->
flags
&
SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX
)
&&
pcm
->
chan
[
0
])
return
pcm
->
chan
[
0
];
if
(
pcm
->
config
->
compat_request_channel
)
return
pcm
->
config
->
compat_request_channel
(
rtd
,
substream
);
return
snd_dmaengine_pcm_request_channel
(
pcm
->
config
->
compat_filter_fn
,
snd_soc_dai_get_dma_data
(
rtd
->
cpu_dai
,
substream
));
}
static
int
dmaengine_pcm_new
(
struct
snd_soc_pcm_runtime
*
rtd
)
{
struct
dmaengine_pcm
*
pcm
=
soc_platform_to_pcm
(
rtd
->
platform
);
const
struct
snd_dmaengine_pcm_config
*
config
=
pcm
->
config
;
struct
snd_pcm_substream
*
substream
;
unsigned
int
i
;
int
ret
;
for
(
i
=
SNDRV_PCM_STREAM_PLAYBACK
;
i
<=
SNDRV_PCM_STREAM_CAPTURE
;
i
++
)
{
substream
=
rtd
->
pcm
->
streams
[
i
].
substream
;
if
(
!
substream
)
continue
;
if
(
!
pcm
->
chan
[
i
]
&&
(
pcm
->
flags
&
SND_DMAENGINE_PCM_FLAG_COMPAT
))
{
pcm
->
chan
[
i
]
=
dmaengine_pcm_compat_request_channel
(
rtd
,
substream
);
}
if
(
!
pcm
->
chan
[
i
])
{
dev_err
(
rtd
->
platform
->
dev
,
"Missing dma channel for stream: %d
\n
"
,
i
);
ret
=
-
EINVAL
;
goto
err_free
;
}
ret
=
snd_pcm_lib_preallocate_pages
(
substream
,
SNDRV_DMA_TYPE_DEV
,
dmaengine_dma_dev
(
pcm
,
substream
),
config
->
prealloc_buffer_size
,
config
->
pcm_hardware
->
buffer_bytes_max
);
if
(
ret
)
goto
err_free
;
}
return
0
;
err_free:
dmaengine_pcm_free
(
rtd
->
pcm
);
return
ret
;
}
static
const
struct
snd_pcm_ops
dmaengine_pcm_ops
=
{
.
open
=
dmaengine_pcm_open
,
.
close
=
snd_dmaengine_pcm_close
,
.
ioctl
=
snd_pcm_lib_ioctl
,
.
hw_params
=
dmaengine_pcm_hw_params
,
.
hw_free
=
snd_pcm_lib_free_pages
,
.
trigger
=
snd_dmaengine_pcm_trigger
,
.
pointer
=
snd_dmaengine_pcm_pointer
,
};
static
const
struct
snd_soc_platform_driver
dmaengine_pcm_platform
=
{
.
ops
=
&
dmaengine_pcm_ops
,
.
pcm_new
=
dmaengine_pcm_new
,
.
pcm_free
=
dmaengine_pcm_free
,
.
probe_order
=
SND_SOC_COMP_ORDER_LATE
,
};
static
const
struct
snd_pcm_ops
dmaengine_no_residue_pcm_ops
=
{
.
open
=
dmaengine_pcm_open
,
.
close
=
snd_dmaengine_pcm_close
,
.
ioctl
=
snd_pcm_lib_ioctl
,
.
hw_params
=
dmaengine_pcm_hw_params
,
.
hw_free
=
snd_pcm_lib_free_pages
,
.
trigger
=
snd_dmaengine_pcm_trigger
,
.
pointer
=
snd_dmaengine_pcm_pointer_no_residue
,
};
static
const
struct
snd_soc_platform_driver
dmaengine_no_residue_pcm_platform
=
{
.
ops
=
&
dmaengine_no_residue_pcm_ops
,
.
pcm_new
=
dmaengine_pcm_new
,
.
pcm_free
=
dmaengine_pcm_free
,
.
probe_order
=
SND_SOC_COMP_ORDER_LATE
,
};
static
const
char
*
const
dmaengine_pcm_dma_channel_names
[]
=
{
[
SNDRV_PCM_STREAM_PLAYBACK
]
=
"tx"
,
[
SNDRV_PCM_STREAM_CAPTURE
]
=
"rx"
,
};
static
void
dmaengine_pcm_request_chan_of
(
struct
dmaengine_pcm
*
pcm
,
struct
device
*
dev
)
{
unsigned
int
i
;
if
((
pcm
->
flags
&
SND_DMAENGINE_PCM_FLAG_NO_DT
)
||
!
dev
->
of_node
)
return
;
if
(
pcm
->
flags
&
SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX
)
{
pcm
->
chan
[
0
]
=
dma_request_slave_channel
(
dev
,
"rx-tx"
);
pcm
->
chan
[
1
]
=
pcm
->
chan
[
0
];
}
else
{
for
(
i
=
SNDRV_PCM_STREAM_PLAYBACK
;
i
<=
SNDRV_PCM_STREAM_CAPTURE
;
i
++
)
{
pcm
->
chan
[
i
]
=
dma_request_slave_channel
(
dev
,
dmaengine_pcm_dma_channel_names
[
i
]);
}
}
}
/**
* snd_dmaengine_pcm_register - Register a dmaengine based PCM device
* @dev: The parent device for the PCM device
* @config: Platform specific PCM configuration
* @flags: Platform specific quirks
*/
int
snd_dmaengine_pcm_register
(
struct
device
*
dev
,
const
struct
snd_dmaengine_pcm_config
*
config
,
unsigned
int
flags
)
{
struct
dmaengine_pcm
*
pcm
;
pcm
=
kzalloc
(
sizeof
(
*
pcm
),
GFP_KERNEL
);
if
(
!
pcm
)
return
-
ENOMEM
;
pcm
->
config
=
config
;
pcm
->
flags
=
flags
;
dmaengine_pcm_request_chan_of
(
pcm
,
dev
);
if
(
flags
&
SND_DMAENGINE_PCM_FLAG_NO_RESIDUE
)
return
snd_soc_add_platform
(
dev
,
&
pcm
->
platform
,
&
dmaengine_no_residue_pcm_platform
);
else
return
snd_soc_add_platform
(
dev
,
&
pcm
->
platform
,
&
dmaengine_pcm_platform
);
}
EXPORT_SYMBOL_GPL
(
snd_dmaengine_pcm_register
);
/**
* snd_dmaengine_pcm_unregister - Removes a dmaengine based PCM device
* @dev: Parent device the PCM was register with
*
* Removes a dmaengine based PCM device previously registered with
* snd_dmaengine_pcm_register.
*/
void
snd_dmaengine_pcm_unregister
(
struct
device
*
dev
)
{
struct
snd_soc_platform
*
platform
;
struct
dmaengine_pcm
*
pcm
;
unsigned
int
i
;
platform
=
snd_soc_lookup_platform
(
dev
);
if
(
!
platform
)
return
;
pcm
=
soc_platform_to_pcm
(
platform
);
for
(
i
=
SNDRV_PCM_STREAM_PLAYBACK
;
i
<=
SNDRV_PCM_STREAM_CAPTURE
;
i
++
)
{
if
(
pcm
->
chan
[
i
])
{
dma_release_channel
(
pcm
->
chan
[
i
]);
if
(
pcm
->
flags
&
SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX
)
break
;
}
}
snd_soc_remove_platform
(
platform
);
kfree
(
pcm
);
}
EXPORT_SYMBOL_GPL
(
snd_dmaengine_pcm_unregister
);
MODULE_LICENSE
(
"GPL"
);
sound/soc/spear/spear_pcm.c
View file @
9eb8ae72
...
...
@@ -64,7 +64,8 @@ static int spear_pcm_open(struct snd_pcm_substream *substream)
if
(
ret
)
return
ret
;
return
snd_dmaengine_pcm_open
(
substream
,
dma_data
->
filter
,
dma_data
)
return
snd_dmaengine_pcm_open_request_chan
(
substream
,
dma_data
->
filter
,
dma_data
);
}
static
int
spear_pcm_mmap
(
struct
snd_pcm_substream
*
substream
,
...
...
@@ -79,7 +80,7 @@ static int spear_pcm_mmap(struct snd_pcm_substream *substream,
static
struct
snd_pcm_ops
spear_pcm_ops
=
{
.
open
=
spear_pcm_open
,
.
close
=
snd_dmaengine_pcm_close
,
.
close
=
snd_dmaengine_pcm_close
_release_chan
,
.
ioctl
=
snd_pcm_lib_ioctl
,
.
hw_params
=
spear_pcm_hw_params
,
.
hw_free
=
spear_pcm_hw_free
,
...
...
sound/soc/tegra/Kconfig
View file @
9eb8ae72
...
...
@@ -2,7 +2,7 @@ config SND_SOC_TEGRA
tristate "SoC Audio for the Tegra System-on-Chip"
depends on ARCH_TEGRA && TEGRA20_APB_DMA
select REGMAP_MMIO
select SND_SOC_DMAENGINE_PCM if TEGRA20_APB_DMA
select SND_SOC_
GENERIC_
DMAENGINE_PCM if TEGRA20_APB_DMA
help
Say Y or M here if you want support for SoC audio on Tegra.
...
...
sound/soc/tegra/tegra_pcm.c
View file @
9eb8ae72
...
...
@@ -29,9 +29,7 @@
*
*/
#include <linux/dma-mapping.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
...
...
@@ -55,175 +53,24 @@ static const struct snd_pcm_hardware tegra_pcm_hardware = {
.
fifo_size
=
4
,
};
static
int
tegra_pcm_open
(
struct
snd_pcm_substream
*
substream
)
{
struct
snd_soc_pcm_runtime
*
rtd
=
substream
->
private_data
;
struct
device
*
dev
=
rtd
->
platform
->
dev
;
int
ret
;
/* Set HW params now that initialization is complete */
snd_soc_set_runtime_hwparams
(
substream
,
&
tegra_pcm_hardware
);
ret
=
snd_dmaengine_pcm_open
(
substream
,
NULL
,
NULL
);
if
(
ret
)
{
dev_err
(
dev
,
"dmaengine pcm open failed with err %d
\n
"
,
ret
);
return
ret
;
}
return
0
;
}
static
int
tegra_pcm_hw_params
(
struct
snd_pcm_substream
*
substream
,
struct
snd_pcm_hw_params
*
params
)
{
struct
snd_soc_pcm_runtime
*
rtd
=
substream
->
private_data
;
struct
device
*
dev
=
rtd
->
platform
->
dev
;
struct
dma_chan
*
chan
=
snd_dmaengine_pcm_get_chan
(
substream
);
struct
dma_slave_config
slave_config
;
int
ret
;
ret
=
snd_hwparams_to_dma_slave_config
(
substream
,
params
,
&
slave_config
);
if
(
ret
)
{
dev_err
(
dev
,
"hw params config failed with err %d
\n
"
,
ret
);
return
ret
;
}
snd_dmaengine_pcm_set_config_from_dai_data
(
substream
,
snd_soc_dai_get_dma_data
(
rtd
->
cpu_dai
,
substream
),
&
slave_config
);
ret
=
dmaengine_slave_config
(
chan
,
&
slave_config
);
if
(
ret
<
0
)
{
dev_err
(
dev
,
"dma slave config failed with err %d
\n
"
,
ret
);
return
ret
;
}
snd_pcm_set_runtime_buffer
(
substream
,
&
substream
->
dma_buffer
);
return
0
;
}
static
int
tegra_pcm_hw_free
(
struct
snd_pcm_substream
*
substream
)
{
snd_pcm_set_runtime_buffer
(
substream
,
NULL
);
return
0
;
}
static
int
tegra_pcm_mmap
(
struct
snd_pcm_substream
*
substream
,
struct
vm_area_struct
*
vma
)
{
struct
snd_pcm_runtime
*
runtime
=
substream
->
runtime
;
return
dma_mmap_writecombine
(
substream
->
pcm
->
card
->
dev
,
vma
,
runtime
->
dma_area
,
runtime
->
dma_addr
,
runtime
->
dma_bytes
);
}
static
struct
snd_pcm_ops
tegra_pcm_ops
=
{
.
open
=
tegra_pcm_open
,
.
close
=
snd_dmaengine_pcm_close
,
.
ioctl
=
snd_pcm_lib_ioctl
,
.
hw_params
=
tegra_pcm_hw_params
,
.
hw_free
=
tegra_pcm_hw_free
,
.
trigger
=
snd_dmaengine_pcm_trigger
,
.
pointer
=
snd_dmaengine_pcm_pointer
,
.
mmap
=
tegra_pcm_mmap
,
};
static
int
tegra_pcm_preallocate_dma_buffer
(
struct
snd_pcm
*
pcm
,
int
stream
)
{
struct
snd_pcm_substream
*
substream
=
pcm
->
streams
[
stream
].
substream
;
struct
snd_dma_buffer
*
buf
=
&
substream
->
dma_buffer
;
size_t
size
=
tegra_pcm_hardware
.
buffer_bytes_max
;
buf
->
area
=
dma_alloc_writecombine
(
pcm
->
card
->
dev
,
size
,
&
buf
->
addr
,
GFP_KERNEL
);
if
(
!
buf
->
area
)
return
-
ENOMEM
;
buf
->
dev
.
type
=
SNDRV_DMA_TYPE_DEV
;
buf
->
dev
.
dev
=
pcm
->
card
->
dev
;
buf
->
private_data
=
NULL
;
buf
->
bytes
=
size
;
return
0
;
}
static
void
tegra_pcm_deallocate_dma_buffer
(
struct
snd_pcm
*
pcm
,
int
stream
)
{
struct
snd_pcm_substream
*
substream
;
struct
snd_dma_buffer
*
buf
;
substream
=
pcm
->
streams
[
stream
].
substream
;
if
(
!
substream
)
return
;
buf
=
&
substream
->
dma_buffer
;
if
(
!
buf
->
area
)
return
;
dma_free_writecombine
(
pcm
->
card
->
dev
,
buf
->
bytes
,
buf
->
area
,
buf
->
addr
);
buf
->
area
=
NULL
;
}
static
u64
tegra_dma_mask
=
DMA_BIT_MASK
(
32
);
static
int
tegra_pcm_new
(
struct
snd_soc_pcm_runtime
*
rtd
)
{
struct
snd_card
*
card
=
rtd
->
card
->
snd_card
;
struct
snd_pcm
*
pcm
=
rtd
->
pcm
;
int
ret
=
0
;
if
(
!
card
->
dev
->
dma_mask
)
card
->
dev
->
dma_mask
=
&
tegra_dma_mask
;
if
(
!
card
->
dev
->
coherent_dma_mask
)
card
->
dev
->
coherent_dma_mask
=
DMA_BIT_MASK
(
32
);
if
(
pcm
->
streams
[
SNDRV_PCM_STREAM_PLAYBACK
].
substream
)
{
ret
=
tegra_pcm_preallocate_dma_buffer
(
pcm
,
SNDRV_PCM_STREAM_PLAYBACK
);
if
(
ret
)
goto
err
;
}
if
(
pcm
->
streams
[
SNDRV_PCM_STREAM_CAPTURE
].
substream
)
{
ret
=
tegra_pcm_preallocate_dma_buffer
(
pcm
,
SNDRV_PCM_STREAM_CAPTURE
);
if
(
ret
)
goto
err_free_play
;
}
return
0
;
err_free_play:
tegra_pcm_deallocate_dma_buffer
(
pcm
,
SNDRV_PCM_STREAM_PLAYBACK
);
err:
return
ret
;
}
static
void
tegra_pcm_free
(
struct
snd_pcm
*
pcm
)
{
tegra_pcm_deallocate_dma_buffer
(
pcm
,
SNDRV_PCM_STREAM_CAPTURE
);
tegra_pcm_deallocate_dma_buffer
(
pcm
,
SNDRV_PCM_STREAM_PLAYBACK
);
}
static
struct
snd_soc_platform_driver
tegra_pcm_platform
=
{
.
ops
=
&
tegra_pcm_ops
,
.
pcm_new
=
tegra_pcm_new
,
.
pcm_free
=
tegra_pcm_free
,
static
const
struct
snd_dmaengine_pcm_config
tegra_dmaengine_pcm_config
=
{
.
pcm_hardware
=
&
tegra_pcm_hardware
,
.
prepare_slave_config
=
snd_dmaengine_pcm_prepare_slave_config
,
.
compat_filter_fn
=
NULL
,
.
prealloc_buffer_size
=
PAGE_SIZE
*
8
,
};
int
tegra_pcm_platform_register
(
struct
device
*
dev
)
{
return
snd_soc_register_platform
(
dev
,
&
tegra_pcm_platform
);
return
snd_dmaengine_pcm_register
(
dev
,
&
tegra_dmaengine_pcm_config
,
SND_DMAENGINE_PCM_FLAG_NO_DT
|
SND_DMAENGINE_PCM_FLAG_COMPAT
);
}
EXPORT_SYMBOL_GPL
(
tegra_pcm_platform_register
);
void
tegra_pcm_platform_unregister
(
struct
device
*
dev
)
{
snd_soc_unregister_platform
(
dev
);
return
snd_dmaengine_pcm_unregister
(
dev
);
}
EXPORT_SYMBOL_GPL
(
tegra_pcm_platform_unregister
);
...
...
sound/soc/ux500/Kconfig
View file @
9eb8ae72
...
...
@@ -16,7 +16,7 @@ config SND_SOC_UX500_PLAT_MSP_I2S
config SND_SOC_UX500_PLAT_DMA
tristate "Platform - DB8500 (DMA)"
depends on SND_SOC_UX500
select SND_SOC_DMAENGINE_PCM
select SND_SOC_
GENERIC_
DMAENGINE_PCM
help
Say Y if you want to enable the Ux500 platform-driver.
...
...
sound/soc/ux500/ux500_pcm.c
View file @
9eb8ae72
...
...
@@ -40,7 +40,7 @@
#define UX500_PLATFORM_PERIODS_MAX 48
#define UX500_PLATFORM_BUFFER_BYTES_MAX (2048 * PAGE_SIZE)
static
struct
snd_pcm_hardware
ux500_pcm_hw
=
{
static
const
struct
snd_pcm_hardware
ux500_pcm_hw
=
{
.
info
=
SNDRV_PCM_INFO_INTERLEAVED
|
SNDRV_PCM_INFO_MMAP
|
SNDRV_PCM_INFO_RESUME
|
...
...
@@ -61,43 +61,23 @@ static struct snd_pcm_hardware ux500_pcm_hw = {
.
periods_max
=
UX500_PLATFORM_PERIODS_MAX
,
};
static
void
ux500_pcm_dma_hw_free
(
struct
device
*
dev
,
struct
snd_pcm_substream
*
substream
)
static
struct
dma_chan
*
ux500_pcm_request_chan
(
struct
snd_soc_pcm_runtime
*
rtd
,
struct
snd_pcm_substream
*
substream
)
{
struct
snd_pcm_runtime
*
runtime
=
substream
->
runtime
;
struct
snd_dma_buffer
*
buf
=
runtime
->
dma_buffer_p
;
if
(
runtime
->
dma_area
==
NULL
)
return
;
if
(
buf
!=
&
substream
->
dma_buffer
)
{
dma_free_coherent
(
buf
->
dev
.
dev
,
buf
->
bytes
,
buf
->
area
,
buf
->
addr
);
kfree
(
runtime
->
dma_buffer_p
);
}
snd_pcm_set_runtime_buffer
(
substream
,
NULL
);
}
static
int
ux500_pcm_open
(
struct
snd_pcm_substream
*
substream
)
{
struct
snd_soc_pcm_runtime
*
rtd
=
substream
->
private_data
;
struct
snd_soc_dai
*
dai
=
rtd
->
cpu_dai
;
struct
device
*
dev
=
dai
->
dev
;
int
ret
;
struct
ux500_msp_dma_params
*
dma_params
;
u16
per_data_width
,
mem_data_width
;
struct
stedma40_chan_cfg
*
dma_cfg
;
struct
ux500_msp_dma_params
*
dma_params
;
dev_dbg
(
dev
,
"%s: MSP %d (%s): Enter.
\n
"
,
__func__
,
dai
->
id
,
snd_pcm_stream_str
(
substream
));
d
ev_dbg
(
dev
,
"%s: Set runtime hwparams.
\n
"
,
__func__
);
snd_soc_set_runtime_hwparams
(
substream
,
&
ux500_pcm_hw
)
;
d
ma_params
=
snd_soc_dai_get_dma_data
(
dai
,
substream
);
dma_cfg
=
dma_params
->
dma_cfg
;
mem_data_width
=
STEDMA40_HALFWORD_WIDTH
;
dma_params
=
snd_soc_dai_get_dma_data
(
dai
,
substream
);
switch
(
dma_params
->
data_size
)
{
case
32
:
per_data_width
=
STEDMA40_WORD_WIDTH
;
...
...
@@ -110,13 +90,8 @@ static int ux500_pcm_open(struct snd_pcm_substream *substream)
break
;
default:
per_data_width
=
STEDMA40_WORD_WIDTH
;
dev_warn
(
rtd
->
platform
->
dev
,
"%s: Unknown data-size (%d)! Assuming 32 bits.
\n
"
,
__func__
,
dma_params
->
data_size
);
}
dma_cfg
=
dma_params
->
dma_cfg
;
if
(
substream
->
stream
==
SNDRV_PCM_STREAM_PLAYBACK
)
{
dma_cfg
->
src_info
.
data_width
=
mem_data_width
;
dma_cfg
->
dst_info
.
data_width
=
per_data_width
;
...
...
@@ -125,123 +100,24 @@ static int ux500_pcm_open(struct snd_pcm_substream *substream)
dma_cfg
->
dst_info
.
data_width
=
mem_data_width
;
}
ret
=
snd_dmaengine_pcm_open
(
substream
,
stedma40_filter
,
dma_cfg
);
if
(
ret
)
{
dev_dbg
(
dai
->
dev
,
"%s: ERROR: snd_dmaengine_pcm_open failed (%d)!
\n
"
,
__func__
,
ret
);
return
ret
;
}
return
0
;
return
snd_dmaengine_pcm_request_channel
(
stedma40_filter
,
dma_cfg
);
}
static
int
ux500_pcm_hw_params
(
struct
snd_pcm_substream
*
substream
,
struct
snd_pcm_hw_params
*
hw_params
)
{
struct
snd_pcm_runtime
*
runtime
=
substream
->
runtime
;
struct
snd_dma_buffer
*
buf
=
runtime
->
dma_buffer_p
;
struct
snd_soc_pcm_runtime
*
rtd
=
substream
->
private_data
;
int
ret
=
0
;
int
size
;
dev_dbg
(
rtd
->
platform
->
dev
,
"%s: Enter
\n
"
,
__func__
);
size
=
params_buffer_bytes
(
hw_params
);
if
(
buf
)
{
if
(
buf
->
bytes
>=
size
)
goto
out
;
ux500_pcm_dma_hw_free
(
NULL
,
substream
);
}
if
(
substream
->
dma_buffer
.
area
!=
NULL
&&
substream
->
dma_buffer
.
bytes
>=
size
)
{
buf
=
&
substream
->
dma_buffer
;
}
else
{
buf
=
kmalloc
(
sizeof
(
struct
snd_dma_buffer
),
GFP_KERNEL
);
if
(
!
buf
)
goto
nomem
;
buf
->
dev
.
type
=
SNDRV_DMA_TYPE_DEV
;
buf
->
dev
.
dev
=
NULL
;
buf
->
area
=
dma_alloc_coherent
(
NULL
,
size
,
&
buf
->
addr
,
GFP_KERNEL
);
buf
->
bytes
=
size
;
buf
->
private_data
=
NULL
;
if
(
!
buf
->
area
)
goto
free
;
}
snd_pcm_set_runtime_buffer
(
substream
,
buf
);
ret
=
1
;
out:
runtime
->
dma_bytes
=
size
;
return
ret
;
free:
kfree
(
buf
);
nomem:
return
-
ENOMEM
;
}
static
int
ux500_pcm_hw_free
(
struct
snd_pcm_substream
*
substream
)
{
struct
snd_soc_pcm_runtime
*
rtd
=
substream
->
private_data
;
dev_dbg
(
rtd
->
platform
->
dev
,
"%s: Enter
\n
"
,
__func__
);
ux500_pcm_dma_hw_free
(
NULL
,
substream
);
return
0
;
}
static
int
ux500_pcm_mmap
(
struct
snd_pcm_substream
*
substream
,
struct
vm_area_struct
*
vma
)
{
struct
snd_pcm_runtime
*
runtime
=
substream
->
runtime
;
struct
snd_soc_pcm_runtime
*
rtd
=
substream
->
private_data
;
dev_dbg
(
rtd
->
platform
->
dev
,
"%s: Enter.
\n
"
,
__func__
);
return
dma_mmap_coherent
(
NULL
,
vma
,
runtime
->
dma_area
,
runtime
->
dma_addr
,
runtime
->
dma_bytes
);
}
static
struct
snd_pcm_ops
ux500_pcm_ops
=
{
.
open
=
ux500_pcm_open
,
.
close
=
snd_dmaengine_pcm_close
,
.
ioctl
=
snd_pcm_lib_ioctl
,
.
hw_params
=
ux500_pcm_hw_params
,
.
hw_free
=
ux500_pcm_hw_free
,
.
trigger
=
snd_dmaengine_pcm_trigger
,
.
pointer
=
snd_dmaengine_pcm_pointer_no_residue
,
.
mmap
=
ux500_pcm_mmap
};
int
ux500_pcm_new
(
struct
snd_soc_pcm_runtime
*
rtd
)
{
struct
snd_pcm
*
pcm
=
rtd
->
pcm
;
dev_dbg
(
rtd
->
platform
->
dev
,
"%s: Enter (id = '%s').
\n
"
,
__func__
,
pcm
->
id
);
pcm
->
info_flags
=
0
;
return
0
;
}
static
struct
snd_soc_platform_driver
ux500_pcm_soc_drv
=
{
.
ops
=
&
ux500_pcm_ops
,
.
pcm_new
=
ux500_pcm_new
,
static
const
struct
snd_dmaengine_pcm_config
ux500_dmaengine_pcm_config
=
{
.
pcm_hardware
=
&
ux500_pcm_hw
,
.
compat_request_channel
=
ux500_pcm_request_chan
,
.
prealloc_buffer_size
=
128
*
1024
,
};
int
ux500_pcm_register_platform
(
struct
platform_device
*
pdev
)
{
int
ret
;
ret
=
snd_soc_register_platform
(
&
pdev
->
dev
,
&
ux500_pcm_soc_drv
);
ret
=
snd_dmaengine_pcm_register
(
&
pdev
->
dev
,
&
ux500_dmaengine_pcm_config
,
SND_DMAENGINE_PCM_FLAG_NO_RESIDUE
|
SND_DMAENGINE_PCM_FLAG_COMPAT
|
SND_DMAENGINE_PCM_FLAG_NO_DT
);
if
(
ret
<
0
)
{
dev_err
(
&
pdev
->
dev
,
"%s: ERROR: Failed to register platform '%s' (%d)!
\n
"
,
...
...
@@ -255,8 +131,7 @@ EXPORT_SYMBOL_GPL(ux500_pcm_register_platform);
int
ux500_pcm_unregister_platform
(
struct
platform_device
*
pdev
)
{
snd_soc_unregister_platform
(
&
pdev
->
dev
);
snd_dmaengine_pcm_unregister
(
&
pdev
->
dev
);
return
0
;
}
EXPORT_SYMBOL_GPL
(
ux500_pcm_unregister_platform
);
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment