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
Kirill Smelkov
linux
Commits
d45a26bd
Commit
d45a26bd
authored
Apr 18, 2013
by
Mark Brown
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'asoc/topic/dma' into asoc-next
parents
8ef53f68
22f38f79
Changes
60
Hide whitespace changes
Inline
Side-by-side
Showing
60 changed files
with
900 additions
and
1083 deletions
+900
-1083
include/sound/dmaengine_pcm.h
include/sound/dmaengine_pcm.h
+88
-4
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
+9
-20
sound/soc/cirrus/edb93xx.c
sound/soc/cirrus/edb93xx.c
+0
-1
sound/soc/cirrus/ep93xx-ac97.c
sound/soc/cirrus/ep93xx-ac97.c
+5
-4
sound/soc/cirrus/ep93xx-i2s.c
sound/soc/cirrus/ep93xx-i2s.c
+8
-8
sound/soc/cirrus/ep93xx-pcm.c
sound/soc/cirrus/ep93xx-pcm.c
+4
-34
sound/soc/cirrus/ep93xx-pcm.h
sound/soc/cirrus/ep93xx-pcm.h
+0
-20
sound/soc/cirrus/simone.c
sound/soc/cirrus/simone.c
+0
-2
sound/soc/cirrus/snappercl15.c
sound/soc/cirrus/snappercl15.c
+0
-1
sound/soc/fsl/Kconfig
sound/soc/fsl/Kconfig
+1
-1
sound/soc/fsl/fsl_ssi.c
sound/soc/fsl/fsl_ssi.c
+35
-20
sound/soc/fsl/imx-pcm-dma.c
sound/soc/fsl/imx-pcm-dma.c
+17
-103
sound/soc/fsl/imx-pcm-fiq.c
sound/soc/fsl/imx-pcm-fiq.c
+2
-2
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
+18
-6
sound/soc/fsl/imx-ssi.c
sound/soc/fsl/imx-ssi.c
+21
-28
sound/soc/fsl/imx-ssi.h
sound/soc/fsl/imx-ssi.h
+5
-2
sound/soc/mxs/mxs-pcm.c
sound/soc/mxs/mxs-pcm.c
+5
-38
sound/soc/mxs/mxs-pcm.h
sound/soc/mxs/mxs-pcm.h
+3
-1
sound/soc/mxs/mxs-saif.c
sound/soc/mxs/mxs-saif.c
+3
-3
sound/soc/omap/am3517evm.c
sound/soc/omap/am3517evm.c
+0
-1
sound/soc/omap/ams-delta.c
sound/soc/omap/ams-delta.c
+0
-1
sound/soc/omap/mcbsp.c
sound/soc/omap/mcbsp.c
+8
-6
sound/soc/omap/mcbsp.h
sound/soc/omap/mcbsp.h
+4
-3
sound/soc/omap/n810.c
sound/soc/omap/n810.c
+0
-1
sound/soc/omap/omap-abe-twl6040.c
sound/soc/omap/omap-abe-twl6040.c
+0
-1
sound/soc/omap/omap-dmic.c
sound/soc/omap/omap-dmic.c
+13
-25
sound/soc/omap/omap-hdmi.c
sound/soc/omap/omap-hdmi.c
+10
-14
sound/soc/omap/omap-mcbsp.c
sound/soc/omap/omap-mcbsp.c
+8
-10
sound/soc/omap/omap-mcpdm.c
sound/soc/omap/omap-mcpdm.c
+65
-44
sound/soc/omap/omap-pcm.c
sound/soc/omap/omap-pcm.c
+9
-77
sound/soc/omap/omap-pcm.h
sound/soc/omap/omap-pcm.h
+0
-40
sound/soc/omap/omap-twl4030.c
sound/soc/omap/omap-twl4030.c
+0
-1
sound/soc/omap/omap3pandora.c
sound/soc/omap/omap3pandora.c
+7
-2
sound/soc/omap/osk5912.c
sound/soc/omap/osk5912.c
+0
-1
sound/soc/omap/rx51.c
sound/soc/omap/rx51.c
+0
-1
sound/soc/pxa/mmp-pcm.c
sound/soc/pxa/mmp-pcm.c
+6
-28
sound/soc/soc-core.c
sound/soc/soc-core.c
+62
-23
sound/soc/soc-dmaengine-pcm.c
sound/soc/soc-dmaengine-pcm.c
+98
-52
sound/soc/soc-generic-dmaengine-pcm.c
sound/soc/soc-generic-dmaengine-pcm.c
+284
-0
sound/soc/spear/spear_pcm.c
sound/soc/spear/spear_pcm.c
+3
-16
sound/soc/tegra/Kconfig
sound/soc/tegra/Kconfig
+1
-1
sound/soc/tegra/tegra20_ac97.c
sound/soc/tegra/tegra20_ac97.c
+7
-6
sound/soc/tegra/tegra20_ac97.h
sound/soc/tegra/tegra20_ac97.h
+2
-2
sound/soc/tegra/tegra20_i2s.c
sound/soc/tegra/tegra20_i2s.c
+7
-6
sound/soc/tegra/tegra20_i2s.h
sound/soc/tegra/tegra20_i2s.h
+2
-2
sound/soc/tegra/tegra20_spdif.c
sound/soc/tegra/tegra20_spdif.c
+4
-3
sound/soc/tegra/tegra20_spdif.h
sound/soc/tegra/tegra20_spdif.h
+2
-2
sound/soc/tegra/tegra30_ahub.c
sound/soc/tegra/tegra30_ahub.c
+4
-4
sound/soc/tegra/tegra30_ahub.h
sound/soc/tegra/tegra30_ahub.h
+4
-4
sound/soc/tegra/tegra30_i2s.c
sound/soc/tegra/tegra30_i2s.c
+7
-6
sound/soc/tegra/tegra30_i2s.h
sound/soc/tegra/tegra30_i2s.h
+2
-2
sound/soc/tegra/tegra_pcm.c
sound/soc/tegra/tegra_pcm.c
+9
-178
sound/soc/tegra/tegra_pcm.h
sound/soc/tegra/tegra_pcm.h
+0
-7
sound/soc/ux500/Kconfig
sound/soc/ux500/Kconfig
+1
-1
sound/soc/ux500/ux500_pcm.c
sound/soc/ux500/ux500_pcm.c
+30
-199
sound/soc/ux500/ux500_pcm.h
sound/soc/ux500/ux500_pcm.h
+0
-14
No files found.
include/sound/dmaengine_pcm.h
View file @
d45a26bd
...
...
@@ -16,6 +16,7 @@
#define __SOUND_DMAENGINE_PCM_H__
#include <sound/pcm.h>
#include <sound/soc.h>
#include <linux/dmaengine.h>
/**
...
...
@@ -32,9 +33,6 @@ snd_pcm_substream_to_dma_direction(const struct snd_pcm_substream *substream)
return
DMA_DEV_TO_MEM
;
}
void
snd_dmaengine_pcm_set_data
(
struct
snd_pcm_substream
*
substream
,
void
*
data
);
void
*
snd_dmaengine_pcm_get_data
(
struct
snd_pcm_substream
*
substream
);
int
snd_hwparams_to_dma_slave_config
(
const
struct
snd_pcm_substream
*
substream
,
const
struct
snd_pcm_hw_params
*
params
,
struct
dma_slave_config
*
slave_config
);
int
snd_dmaengine_pcm_trigger
(
struct
snd_pcm_substream
*
substream
,
int
cmd
);
...
...
@@ -42,9 +40,95 @@ 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
);
/**
* struct snd_dmaengine_dai_dma_data - DAI DMA configuration data
* @addr: Address of the DAI data source or destination register.
* @addr_width: Width of the DAI data source or destination register.
* @maxburst: Maximum number of words(note: words, as in units of the
* src_addr_width member, not bytes) that can be send to or received from the
* DAI in one burst.
* @slave_id: Slave requester id for the DMA channel.
* @filter_data: Custom DMA channel filter data, this will usually be used when
* requesting the DMA channel.
*/
struct
snd_dmaengine_dai_dma_data
{
dma_addr_t
addr
;
enum
dma_slave_buswidth
addr_width
;
u32
maxburst
;
unsigned
int
slave_id
;
void
*
filter_data
;
};
void
snd_dmaengine_pcm_set_config_from_dai_data
(
const
struct
snd_pcm_substream
*
substream
,
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)
/**
* 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 @
d45a26bd
...
...
@@ -373,6 +373,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 @
d45a26bd
...
...
@@ -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 @
d45a26bd
...
...
@@ -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 @
d45a26bd
...
...
@@ -67,9 +67,10 @@ static const struct snd_pcm_hardware atmel_pcm_dma_hardware = {
static
void
atmel_pcm_dma_irq
(
u32
ssc_sr
,
struct
snd_pcm_substream
*
substream
)
{
struct
snd_soc_pcm_runtime
*
rtd
=
substream
->
private_data
;
struct
atmel_pcm_dma_params
*
prtd
;
prtd
=
snd_
dmaengine_pcm_get_data
(
substream
);
prtd
=
snd_
soc_dai_get_dma_data
(
rtd
->
cpu_dai
,
substream
);
if
(
ssc_sr
&
prtd
->
mask
->
ssc_error
)
{
if
(
snd_pcm_running
(
substream
))
...
...
@@ -104,15 +105,13 @@ static bool filter(struct dma_chan *chan, void *slave)
}
static
int
atmel_pcm_configure_dma
(
struct
snd_pcm_substream
*
substream
,
struct
snd_pcm_hw_params
*
params
)
struct
snd_pcm_hw_params
*
params
,
struct
atmel_pcm_dma_params
*
prtd
)
{
struct
atmel_pcm_dma_params
*
prtd
;
struct
ssc_device
*
ssc
;
struct
dma_chan
*
dma_chan
;
struct
dma_slave_config
slave_config
;
int
ret
;
prtd
=
snd_dmaengine_pcm_get_data
(
substream
);
ssc
=
prtd
->
ssc
;
ret
=
snd_hwparams_to_dma_slave_config
(
substream
,
params
,
...
...
@@ -130,8 +129,6 @@ static int atmel_pcm_configure_dma(struct snd_pcm_substream *substream,
slave_config
.
src_maxburst
=
1
;
}
slave_config
.
device_fc
=
false
;
dma_chan
=
snd_dmaengine_pcm_get_chan
(
substream
);
if
(
dmaengine_slave_config
(
dma_chan
,
&
slave_config
))
{
pr_err
(
"atmel-pcm: failed to configure dma channel
\n
"
);
...
...
@@ -158,15 +155,13 @@ 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
;
}
snd_dmaengine_pcm_set_data
(
substream
,
prtd
);
ret
=
atmel_pcm_configure_dma
(
substream
,
params
);
ret
=
atmel_pcm_configure_dma
(
substream
,
params
,
prtd
);
if
(
ret
)
{
pr_err
(
"atmel-pcm: failed to configure dmai
\n
"
);
goto
err
;
...
...
@@ -176,15 +171,16 @@ 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
;
}
static
int
atmel_pcm_dma_prepare
(
struct
snd_pcm_substream
*
substream
)
{
struct
snd_soc_pcm_runtime
*
rtd
=
substream
->
private_data
;
struct
atmel_pcm_dma_params
*
prtd
;
prtd
=
snd_
dmaengine_pcm_get_data
(
substream
);
prtd
=
snd_
soc_dai_get_dma_data
(
rtd
->
cpu_dai
,
substream
);
ssc_writex
(
prtd
->
ssc
->
regs
,
SSC_IER
,
prtd
->
mask
->
ssc_error
);
ssc_writex
(
prtd
->
ssc
->
regs
,
SSC_CR
,
prtd
->
mask
->
ssc_enable
);
...
...
@@ -199,16 +195,9 @@ static int atmel_pcm_open(struct snd_pcm_substream *substream)
return
0
;
}
static
int
atmel_pcm_close
(
struct
snd_pcm_substream
*
substream
)
{
snd_dmaengine_pcm_close
(
substream
);
return
0
;
}
static
struct
snd_pcm_ops
atmel_pcm_ops
=
{
.
open
=
atmel_pcm_open
,
.
close
=
atmel_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/edb93xx.c
View file @
d45a26bd
...
...
@@ -27,7 +27,6 @@
#include <sound/soc.h>
#include <asm/mach-types.h>
#include <mach/hardware.h>
#include "ep93xx-pcm.h"
static
int
edb93xx_hw_params
(
struct
snd_pcm_substream
*
substream
,
struct
snd_pcm_hw_params
*
params
)
...
...
sound/soc/cirrus/ep93xx-ac97.c
View file @
d45a26bd
...
...
@@ -23,7 +23,6 @@
#include <sound/soc.h>
#include <linux/platform_data/dma-ep93xx.h>
#include "ep93xx-pcm.h"
/*
* Per channel (1-4) registers.
...
...
@@ -101,14 +100,16 @@ struct ep93xx_ac97_info {
/* currently ALSA only supports a single AC97 device */
static
struct
ep93xx_ac97_info
*
ep93xx_ac97_info
;
static
struct
ep93xx_
pcm_dma_params
ep93xx_ac97_pcm_out
=
{
static
struct
ep93xx_
dma_data
ep93xx_ac97_pcm_out
=
{
.
name
=
"ac97-pcm-out"
,
.
dma_port
=
EP93XX_DMA_AAC1
,
.
direction
=
DMA_MEM_TO_DEV
,
};
static
struct
ep93xx_
pcm_dma_params
ep93xx_ac97_pcm_in
=
{
static
struct
ep93xx_
dma_data
ep93xx_ac97_pcm_in
=
{
.
name
=
"ac97-pcm-in"
,
.
dma_port
=
EP93XX_DMA_AAC1
,
.
direction
=
DMA_DEV_TO_MEM
,
};
static
inline
unsigned
ep93xx_ac97_read_reg
(
struct
ep93xx_ac97_info
*
info
,
...
...
@@ -316,7 +317,7 @@ static int ep93xx_ac97_trigger(struct snd_pcm_substream *substream,
static
int
ep93xx_ac97_startup
(
struct
snd_pcm_substream
*
substream
,
struct
snd_soc_dai
*
dai
)
{
struct
ep93xx_
pcm_dma_params
*
dma_data
;
struct
ep93xx_
dma_data
*
dma_data
;
if
(
substream
->
stream
==
SNDRV_PCM_STREAM_PLAYBACK
)
dma_data
=
&
ep93xx_ac97_pcm_out
;
...
...
sound/soc/cirrus/ep93xx-i2s.c
View file @
d45a26bd
...
...
@@ -30,8 +30,6 @@
#include <mach/ep93xx-regs.h>
#include <linux/platform_data/dma-ep93xx.h>
#include "ep93xx-pcm.h"
#define EP93XX_I2S_TXCLKCFG 0x00
#define EP93XX_I2S_RXCLKCFG 0x04
#define EP93XX_I2S_GLCTRL 0x0C
...
...
@@ -62,18 +60,20 @@ struct ep93xx_i2s_info {
struct
clk
*
mclk
;
struct
clk
*
sclk
;
struct
clk
*
lrclk
;
struct
ep93xx_
pcm_dma_params
*
dma_params
;
struct
ep93xx_
dma_data
*
dma_data
;
void
__iomem
*
regs
;
};
struct
ep93xx_
pcm_dma_params
ep93xx_i2s_dma_params
[]
=
{
struct
ep93xx_
dma_data
ep93xx_i2s_dma_data
[]
=
{
[
SNDRV_PCM_STREAM_PLAYBACK
]
=
{
.
name
=
"i2s-pcm-out"
,
.
dma_port
=
EP93XX_DMA_I2S1
,
.
port
=
EP93XX_DMA_I2S1
,
.
direction
=
DMA_MEM_TO_DEV
,
},
[
SNDRV_PCM_STREAM_CAPTURE
]
=
{
.
name
=
"i2s-pcm-in"
,
.
dma_port
=
EP93XX_DMA_I2S1
,
.
port
=
EP93XX_DMA_I2S1
,
.
direction
=
DMA_DEV_TO_MEM
,
},
};
...
...
@@ -147,7 +147,7 @@ static int ep93xx_i2s_startup(struct snd_pcm_substream *substream,
struct
snd_soc_dai
*
cpu_dai
=
rtd
->
cpu_dai
;
snd_soc_dai_set_dma_data
(
cpu_dai
,
substream
,
&
info
->
dma_
params
[
substream
->
stream
]);
&
info
->
dma_
data
[
substream
->
stream
]);
return
0
;
}
...
...
@@ -403,7 +403,7 @@ static int ep93xx_i2s_probe(struct platform_device *pdev)
}
dev_set_drvdata
(
&
pdev
->
dev
,
info
);
info
->
dma_
params
=
ep93xx_i2s_dma_params
;
info
->
dma_
data
=
ep93xx_i2s_dma_data
;
err
=
snd_soc_register_dai
(
&
pdev
->
dev
,
&
ep93xx_i2s_dai
);
if
(
err
)
...
...
sound/soc/cirrus/ep93xx-pcm.c
View file @
d45a26bd
...
...
@@ -29,8 +29,6 @@
#include <mach/hardware.h>
#include <mach/ep93xx-regs.h>
#include "ep93xx-pcm.h"
static
const
struct
snd_pcm_hardware
ep93xx_pcm_hardware
=
{
.
info
=
(
SNDRV_PCM_INFO_MMAP
|
SNDRV_PCM_INFO_MMAP_VALID
|
...
...
@@ -68,40 +66,12 @@ static bool ep93xx_pcm_dma_filter(struct dma_chan *chan, void *filter_param)
static
int
ep93xx_pcm_open
(
struct
snd_pcm_substream
*
substream
)
{
struct
snd_soc_pcm_runtime
*
rtd
=
substream
->
private_data
;
struct
snd_soc_dai
*
cpu_dai
=
rtd
->
cpu_dai
;
struct
ep93xx_pcm_dma_params
*
dma_params
;
struct
ep93xx_dma_data
*
dma_data
;
int
ret
;
snd_soc_set_runtime_hwparams
(
substream
,
&
ep93xx_pcm_hardware
);
dma_data
=
kmalloc
(
sizeof
(
*
dma_data
),
GFP_KERNEL
);
if
(
!
dma_data
)
return
-
ENOMEM
;
dma_params
=
snd_soc_dai_get_dma_data
(
cpu_dai
,
substream
);
dma_data
->
port
=
dma_params
->
dma_port
;
dma_data
->
name
=
dma_params
->
name
;
dma_data
->
direction
=
snd_pcm_substream_to_dma_direction
(
substream
);
ret
=
snd_dmaengine_pcm_open
(
substream
,
ep93xx_pcm_dma_filter
,
dma_data
);
if
(
ret
)
{
kfree
(
dma_data
);
return
ret
;
}
snd_dmaengine_pcm_set_data
(
substream
,
dma_data
);
return
0
;
}
static
int
ep93xx_pcm_close
(
struct
snd_pcm_substream
*
substream
)
{
struct
dma_data
*
dma_data
=
snd_dmaengine_pcm_get_data
(
substream
);
snd_dmaengine_pcm_close
(
substream
);
kfree
(
dma_data
);
return
0
;
return
snd_dmaengine_pcm_open_request_chan
(
substream
,
ep93xx_pcm_dma_filter
,
snd_soc_dai_get_dma_data
(
rtd
->
cpu_dai
,
substream
));
}
static
int
ep93xx_pcm_hw_params
(
struct
snd_pcm_substream
*
substream
,
...
...
@@ -131,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
=
ep93xx_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/cirrus/ep93xx-pcm.h
deleted
100644 → 0
View file @
8ef53f68
/*
* sound/soc/ep93xx/ep93xx-pcm.h - EP93xx ALSA PCM interface
*
* Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
* Copyright (C) 2006 Applied Data Systems
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef _EP93XX_SND_SOC_PCM_H
#define _EP93XX_SND_SOC_PCM_H
struct
ep93xx_pcm_dma_params
{
char
*
name
;
int
dma_port
;
};
#endif
/* _EP93XX_SND_SOC_PCM_H */
sound/soc/cirrus/simone.c
View file @
d45a26bd
...
...
@@ -21,8 +21,6 @@
#include <asm/mach-types.h>
#include <mach/hardware.h>
#include "ep93xx-pcm.h"
static
struct
snd_soc_dai_link
simone_dai
=
{
.
name
=
"AC97"
,
.
stream_name
=
"AC97 HiFi"
,
...
...
sound/soc/cirrus/snappercl15.c
View file @
d45a26bd
...
...
@@ -21,7 +21,6 @@
#include <mach/hardware.h>
#include "../codecs/tlv320aic23.h"
#include "ep93xx-pcm.h"
#define CODEC_CLOCK 5644800
...
...
sound/soc/fsl/Kconfig
View file @
d45a26bd
...
...
@@ -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 @
d45a26bd
...
...
@@ -27,6 +27,7 @@
#include <sound/pcm_params.h>
#include <sound/initval.h>
#include <sound/soc.h>
#include <sound/dmaengine_pcm.h>
#include "fsl_ssi.h"
#include "imx-pcm.h"
...
...
@@ -122,8 +123,10 @@ struct fsl_ssi_private {
bool
ssi_on_imx
;
struct
clk
*
clk
;
struct
platform_device
*
imx_pcm_pdev
;
struct
imx_pcm_dma_params
dma_params_tx
;
struct
imx_pcm_dma_params
dma_params_rx
;
struct
snd_dmaengine_dai_dma_data
dma_params_tx
;
struct
snd_dmaengine_dai_dma_data
dma_params_rx
;
struct
imx_dma_data
filter_data_tx
;
struct
imx_dma_data
filter_data_rx
;
struct
{
unsigned
int
rfrc
;
...
...
@@ -422,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
;
}
...
...
@@ -549,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
,
...
...
@@ -558,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
,
...
...
@@ -649,6 +659,7 @@ static int fsl_ssi_probe(struct platform_device *pdev)
const
uint32_t
*
iprop
;
struct
resource
res
;
char
name
[
64
];
bool
shared
;
/* SSIs that are not connected on the board should have a
* status = "disabled"
...
...
@@ -737,14 +748,18 @@ static int fsl_ssi_probe(struct platform_device *pdev)
* We have burstsize be "fifo_depth - 2" to match the SSI
* watermark setting in fsl_ssi_startup().
*/
ssi_private
->
dma_params_tx
.
burstsize
=
ssi_private
->
dma_params_tx
.
maxburst
=
ssi_private
->
fifo_depth
-
2
;
ssi_private
->
dma_params_rx
.
burstsize
=
ssi_private
->
dma_params_rx
.
maxburst
=
ssi_private
->
fifo_depth
-
2
;
ssi_private
->
dma_params_tx
.
dma_
addr
=
ssi_private
->
dma_params_tx
.
addr
=
ssi_private
->
ssi_phys
+
offsetof
(
struct
ccsr_ssi
,
stx0
);
ssi_private
->
dma_params_rx
.
dma_
addr
=
ssi_private
->
dma_params_rx
.
addr
=
ssi_private
->
ssi_phys
+
offsetof
(
struct
ccsr_ssi
,
srx0
);
ssi_private
->
dma_params_tx
.
filter_data
=
&
ssi_private
->
filter_data_tx
;
ssi_private
->
dma_params_rx
.
filter_data
=
&
ssi_private
->
filter_data_rx
;
/*
* TODO: This is a temporary solution and should be changed
* to use generic DMA binding later when the helplers get in.
...
...
@@ -755,14 +770,14 @@ static int fsl_ssi_probe(struct platform_device *pdev)
dev_err
(
&
pdev
->
dev
,
"could not get dma events
\n
"
);
goto
error_clk
;
}
ssi_private
->
dma_params_tx
.
dma
=
dma_events
[
0
];
s
si_private
->
dma_params_rx
.
dma
=
dma_events
[
1
];
ssi_private
->
dma_params_tx
.
shared_peripheral
=
of_device_is_compatible
(
of_get_parent
(
np
)
,
"fsl,spba-bus"
);
ssi_private
->
dma_params_rx
.
shared_peripheral
=
ssi_private
->
dma_params_tx
.
shared_peripheral
;
s
hared
=
of_device_is_compatible
(
of_get_parent
(
np
),
"fsl,spba-bus"
);
imx_pcm_dma_params_init_data
(
&
ssi_private
->
filter_data_tx
,
dma_events
[
0
],
shared
);
imx_pcm_dma_params_init_data
(
&
ssi_private
->
filter_data_rx
,
dma_events
[
1
],
shared
)
;
}
/* Initialize the the device_attribute structure */
...
...
sound/soc/fsl/imx-pcm-dma.c
View file @
d45a26bd
...
...
@@ -11,74 +11,30 @@
* 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>
#include <linux/platform_data/dma-imx.h>
#include "imx-pcm.h"
static
bool
filter
(
struct
dma_chan
*
chan
,
void
*
param
)
{
struct
snd_dmaengine_dai_dma_data
*
dma_data
=
param
;
if
(
!
imx_dma_is_general_purpose
(
chan
))
return
false
;
chan
->
private
=
param
;
chan
->
private
=
dma_data
->
filter_data
;
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
imx_pcm_dma_params
*
dma_params
;
struct
dma_slave_config
slave_config
;
int
ret
;
dma_params
=
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
;
slave_config
.
device_fc
=
false
;
if
(
substream
->
stream
==
SNDRV_PCM_STREAM_PLAYBACK
)
{
slave_config
.
dst_addr
=
dma_params
->
dma_addr
;
slave_config
.
dst_maxburst
=
dma_params
->
burstsize
;
}
else
{
slave_config
.
src_addr
=
dma_params
->
dma_addr
;
slave_config
.
src_maxburst
=
dma_params
->
burstsize
;
}
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
|
...
...
@@ -97,64 +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
;
struct
imx_pcm_dma_params
*
dma_params
;
struct
imx_dma_data
*
dma_data
;
int
ret
;
snd_soc_set_runtime_hwparams
(
substream
,
&
snd_imx_hardware
);
dma_params
=
snd_soc_dai_get_dma_data
(
rtd
->
cpu_dai
,
substream
);
dma_data
=
kzalloc
(
sizeof
(
*
dma_data
),
GFP_KERNEL
);
if
(
!
dma_data
)
return
-
ENOMEM
;
dma_data
->
peripheral_type
=
dma_params
->
shared_peripheral
?
IMX_DMATYPE_SSI_SP
:
IMX_DMATYPE_SSI
;
dma_data
->
priority
=
DMA_PRIO_HIGH
;
dma_data
->
dma_request
=
dma_params
->
dma
;
ret
=
snd_dmaengine_pcm_open
(
substream
,
filter
,
dma_data
);
if
(
ret
)
{
kfree
(
dma_data
);
return
ret
;
}
snd_dmaengine_pcm_set_data
(
substream
,
dma_data
);
return
0
;
}
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
,
};
static
int
snd_imx_close
(
struct
snd_pcm_substream
*
substream
)
int
imx_pcm_dma_init
(
struct
platform_device
*
pdev
)
{
struct
imx_dma_data
*
dma_data
=
snd_dmaengine_pcm_get_data
(
substream
);
snd_dmaengine_pcm_close
(
substream
);
kfree
(
dma_data
);
return
0
;
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
);
}
static
struct
snd_pcm_ops
imx_pcm_ops
=
{
.
open
=
snd_imx_open
,
.
close
=
snd_imx_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
,
};
int
imx_pcm_dma_init
(
struct
platform_device
*
pdev
)
void
imx_pcm_dma_exit
(
struct
platform_device
*
pdev
)
{
return
snd_soc_register_platform
(
&
pdev
->
dev
,
&
imx_soc_platform_mx2
);
snd_dmaengine_pcm_unregister
(
&
pdev
->
dev
);
}
sound/soc/fsl/imx-pcm-fiq.c
View file @
d45a26bd
...
...
@@ -299,8 +299,8 @@ int imx_pcm_fiq_init(struct platform_device *pdev)
imx_ssi_fiq_base
=
(
unsigned
long
)
ssi
->
base
;
ssi
->
dma_params_tx
.
burstsize
=
4
;
ssi
->
dma_params_rx
.
burstsize
=
6
;
ssi
->
dma_params_tx
.
maxburst
=
4
;
ssi
->
dma_params_rx
.
maxburst
=
6
;
ret
=
snd_soc_register_platform
(
&
pdev
->
dev
,
&
imx_soc_platform_fiq
);
if
(
ret
)
...
...
sound/soc/fsl/imx-pcm.c
View file @
d45a26bd
...
...
@@ -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 @
d45a26bd
...
...
@@ -13,17 +13,24 @@
#ifndef _IMX_PCM_H
#define _IMX_PCM_H
#include <linux/platform_data/dma-imx.h>
/*
* Do not change this as the FIQ handler depends on this size
*/
#define IMX_SSI_DMABUF_SIZE (64 * 1024)
struct
imx_pcm_dma_params
{
int
dma
;
unsigned
long
dma_addr
;
int
burstsize
;
bool
shared_peripheral
;
/* The peripheral is on SPBA bus */
};
static
inline
void
imx_pcm_dma_params_init_data
(
struct
imx_dma_data
*
dma_data
,
int
dma
,
bool
shared
)
{
dma_data
->
dma_request
=
dma
;
dma_data
->
priority
=
DMA_PRIO_HIGH
;
if
(
shared
)
dma_data
->
peripheral_type
=
IMX_DMATYPE_SSI_SP
;
else
dma_data
->
peripheral_type
=
IMX_DMATYPE_SSI
;
}
int
snd_imx_pcm_mmap
(
struct
snd_pcm_substream
*
substream
,
struct
vm_area_struct
*
vma
);
...
...
@@ -32,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 @
d45a26bd
...
...
@@ -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
imx_pcm_dma_params
*
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
,
...
...
@@ -369,10 +351,14 @@ static int imx_ssi_dai_probe(struct snd_soc_dai *dai)
snd_soc_dai_set_drvdata
(
dai
,
ssi
);
val
=
SSI_SFCSR_TFWM0
(
ssi
->
dma_params_tx
.
burstsize
)
|
SSI_SFCSR_RFWM0
(
ssi
->
dma_params_rx
.
burstsize
);
val
=
SSI_SFCSR_TFWM0
(
ssi
->
dma_params_tx
.
maxburst
)
|
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
;
}
...
...
@@ -575,19 +561,26 @@ static int imx_ssi_probe(struct platform_device *pdev)
writel
(
0x0
,
ssi
->
base
+
SSI_SIER
);
ssi
->
dma_params_rx
.
dma_addr
=
res
->
start
+
SSI_SRX0
;
ssi
->
dma_params_tx
.
dma_addr
=
res
->
start
+
SSI_STX0
;
ssi
->
dma_params_rx
.
addr
=
res
->
start
+
SSI_SRX0
;
ssi
->
dma_params_tx
.
addr
=
res
->
start
+
SSI_STX0
;
ssi
->
dma_params_tx
.
maxburst
=
6
;
ssi
->
dma_params_rx
.
maxburst
=
4
;
ssi
->
dma_params_tx
.
burstsize
=
6
;
ssi
->
dma_params_rx
.
burstsize
=
4
;
ssi
->
dma_params_tx
.
filter_data
=
&
ssi
->
filter_data_tx
;
ssi
->
dma_params_rx
.
filter_data
=
&
ssi
->
filter_data_rx
;
res
=
platform_get_resource_byname
(
pdev
,
IORESOURCE_DMA
,
"tx0"
);
if
(
res
)
ssi
->
dma_params_tx
.
dma
=
res
->
start
;
if
(
res
)
{
imx_pcm_dma_params_init_data
(
&
ssi
->
filter_data_tx
,
res
->
start
,
false
);
}
res
=
platform_get_resource_byname
(
pdev
,
IORESOURCE_DMA
,
"rx0"
);
if
(
res
)
ssi
->
dma_params_rx
.
dma
=
res
->
start
;
if
(
res
)
{
imx_pcm_dma_params_init_data
(
&
ssi
->
filter_data_rx
,
res
->
start
,
false
);
}
platform_set_drvdata
(
pdev
,
ssi
);
...
...
sound/soc/fsl/imx-ssi.h
View file @
d45a26bd
...
...
@@ -187,6 +187,7 @@
#include <linux/dmaengine.h>
#include <linux/platform_data/dma-imx.h>
#include <sound/dmaengine_pcm.h>
#include "imx-pcm.h"
struct
imx_ssi
{
...
...
@@ -204,8 +205,10 @@ struct imx_ssi {
void
(
*
ac97_reset
)
(
struct
snd_ac97
*
ac97
);
void
(
*
ac97_warm_reset
)(
struct
snd_ac97
*
ac97
);
struct
imx_pcm_dma_params
dma_params_rx
;
struct
imx_pcm_dma_params
dma_params_tx
;
struct
snd_dmaengine_dai_dma_data
dma_params_rx
;
struct
snd_dmaengine_dai_dma_data
dma_params_tx
;
struct
imx_dma_data
filter_data_tx
;
struct
imx_dma_data
filter_data_rx
;
int
enabled
;
...
...
sound/soc/mxs/mxs-pcm.c
View file @
d45a26bd
...
...
@@ -28,7 +28,6 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/dmaengine.h>
#include <linux/fsl/mxs-dma.h>
#include <sound/core.h>
#include <sound/initval.h>
...
...
@@ -39,11 +38,6 @@
#include "mxs-pcm.h"
struct
mxs_pcm_dma_data
{
struct
mxs_dma_data
dma_data
;
struct
mxs_pcm_dma_params
*
dma_params
;
};
static
struct
snd_pcm_hardware
snd_mxs_hardware
=
{
.
info
=
SNDRV_PCM_INFO_MMAP
|
SNDRV_PCM_INFO_MMAP_VALID
|
...
...
@@ -66,8 +60,7 @@ static struct snd_pcm_hardware snd_mxs_hardware = {
static
bool
filter
(
struct
dma_chan
*
chan
,
void
*
param
)
{
struct
mxs_pcm_dma_data
*
pcm_dma_data
=
param
;
struct
mxs_pcm_dma_params
*
dma_params
=
pcm_dma_data
->
dma_params
;
struct
mxs_pcm_dma_params
*
dma_params
=
param
;
if
(
!
mxs_dma_is_apbx
(
chan
))
return
false
;
...
...
@@ -75,7 +68,7 @@ static bool filter(struct dma_chan *chan, void *param)
if
(
chan
->
chan_id
!=
dma_params
->
chan_num
)
return
false
;
chan
->
private
=
&
pcm_dma_data
->
dma_data
;
chan
->
private
=
&
dma_params
->
dma_data
;
return
true
;
}
...
...
@@ -91,37 +84,11 @@ static int snd_mxs_pcm_hw_params(struct snd_pcm_substream *substream,
static
int
snd_mxs_open
(
struct
snd_pcm_substream
*
substream
)
{
struct
snd_soc_pcm_runtime
*
rtd
=
substream
->
private_data
;
struct
mxs_pcm_dma_data
*
pcm_dma_data
;
int
ret
;
pcm_dma_data
=
kzalloc
(
sizeof
(
*
pcm_dma_data
),
GFP_KERNEL
);
if
(
pcm_dma_data
==
NULL
)
return
-
ENOMEM
;
pcm_dma_data
->
dma_params
=
snd_soc_dai_get_dma_data
(
rtd
->
cpu_dai
,
substream
);
pcm_dma_data
->
dma_data
.
chan_irq
=
pcm_dma_data
->
dma_params
->
chan_irq
;
ret
=
snd_dmaengine_pcm_open
(
substream
,
filter
,
pcm_dma_data
);
if
(
ret
)
{
kfree
(
pcm_dma_data
);
return
ret
;
}
snd_soc_set_runtime_hwparams
(
substream
,
&
snd_mxs_hardware
);
snd_dmaengine_pcm_set_data
(
substream
,
pcm_dma_data
);
return
0
;
}
static
int
snd_mxs_close
(
struct
snd_pcm_substream
*
substream
)
{
struct
mxs_pcm_dma_data
*
pcm_dma_data
=
snd_dmaengine_pcm_get_data
(
substream
);
snd_dmaengine_pcm_close
(
substream
);
kfree
(
pcm_dma_data
);
return
0
;
return
snd_dmaengine_pcm_open_request_chan
(
substream
,
filter
,
snd_soc_dai_get_dma_data
(
rtd
->
cpu_dai
,
substream
));
}
static
int
snd_mxs_pcm_mmap
(
struct
snd_pcm_substream
*
substream
,
...
...
@@ -137,7 +104,7 @@ static int snd_mxs_pcm_mmap(struct snd_pcm_substream *substream,
static
struct
snd_pcm_ops
mxs_pcm_ops
=
{
.
open
=
snd_mxs_open
,
.
close
=
snd_
mxs_close
,
.
close
=
snd_
dmaengine_pcm_close_release_chan
,
.
ioctl
=
snd_pcm_lib_ioctl
,
.
hw_params
=
snd_mxs_pcm_hw_params
,
.
trigger
=
snd_dmaengine_pcm_trigger
,
...
...
sound/soc/mxs/mxs-pcm.h
View file @
d45a26bd
...
...
@@ -19,8 +19,10 @@
#ifndef _MXS_PCM_H
#define _MXS_PCM_H
#include <linux/fsl/mxs-dma.h>
struct
mxs_pcm_dma_params
{
int
chan_irq
;
struct
mxs_dma_data
dma_data
;
int
chan_num
;
};
...
...
sound/soc/mxs/mxs-saif.c
View file @
d45a26bd
...
...
@@ -753,9 +753,9 @@ static int mxs_saif_probe(struct platform_device *pdev)
return
ret
;
}
saif
->
dma_param
.
chan_irq
=
platform_get_irq
(
pdev
,
1
);
if
(
saif
->
dma_param
.
chan_irq
<
0
)
{
ret
=
saif
->
dma_param
.
chan_irq
;
saif
->
dma_param
.
dma_data
.
chan_irq
=
platform_get_irq
(
pdev
,
1
);
if
(
saif
->
dma_param
.
dma_data
.
chan_irq
<
0
)
{
ret
=
saif
->
dma_param
.
dma_data
.
chan_irq
;
dev_err
(
&
pdev
->
dev
,
"failed to get dma irq resource: %d
\n
"
,
ret
);
return
ret
;
...
...
sound/soc/omap/am3517evm.c
View file @
d45a26bd
...
...
@@ -28,7 +28,6 @@
#include <linux/platform_data/asoc-ti-mcbsp.h>
#include "omap-mcbsp.h"
#include "omap-pcm.h"
#include "../codecs/tlv320aic23.h"
...
...
sound/soc/omap/ams-delta.c
View file @
d45a26bd
...
...
@@ -36,7 +36,6 @@
#include <linux/platform_data/asoc-ti-mcbsp.h>
#include "omap-mcbsp.h"
#include "omap-pcm.h"
#include "../codecs/cx20442.h"
...
...
sound/soc/omap/mcbsp.c
View file @
d45a26bd
...
...
@@ -1018,9 +1018,10 @@ int omap_mcbsp_init(struct platform_device *pdev)
return
-
ENODEV
;
}
/* RX DMA request number, and port address configuration */
mcbsp
->
dma_data
[
1
].
name
=
"Audio Capture"
;
mcbsp
->
dma_data
[
1
].
dma_req
=
res
->
start
;
mcbsp
->
dma_data
[
1
].
port_addr
=
omap_mcbsp_dma_reg_params
(
mcbsp
,
1
);
mcbsp
->
dma_req
[
1
]
=
res
->
start
;
mcbsp
->
dma_data
[
1
].
filter_data
=
&
mcbsp
->
dma_req
[
1
];
mcbsp
->
dma_data
[
1
].
addr
=
omap_mcbsp_dma_reg_params
(
mcbsp
,
1
);
mcbsp
->
dma_data
[
1
].
maxburst
=
4
;
res
=
platform_get_resource_byname
(
pdev
,
IORESOURCE_DMA
,
"tx"
);
if
(
!
res
)
{
...
...
@@ -1028,9 +1029,10 @@ int omap_mcbsp_init(struct platform_device *pdev)
return
-
ENODEV
;
}
/* TX DMA request number, and port address configuration */
mcbsp
->
dma_data
[
0
].
name
=
"Audio Playback"
;
mcbsp
->
dma_data
[
0
].
dma_req
=
res
->
start
;
mcbsp
->
dma_data
[
0
].
port_addr
=
omap_mcbsp_dma_reg_params
(
mcbsp
,
0
);
mcbsp
->
dma_req
[
0
]
=
res
->
start
;
mcbsp
->
dma_data
[
0
].
filter_data
=
&
mcbsp
->
dma_req
[
0
];
mcbsp
->
dma_data
[
0
].
addr
=
omap_mcbsp_dma_reg_params
(
mcbsp
,
0
);
mcbsp
->
dma_data
[
0
].
maxburst
=
4
;
mcbsp
->
fclk
=
clk_get
(
&
pdev
->
dev
,
"fck"
);
if
(
IS_ERR
(
mcbsp
->
fclk
))
{
...
...
sound/soc/omap/mcbsp.h
View file @
d45a26bd
...
...
@@ -24,14 +24,14 @@
#ifndef __ASOC_MCBSP_H
#define __ASOC_MCBSP_H
#include "omap-pcm.h"
#ifdef CONFIG_ARCH_OMAP1
#define mcbsp_omap1() 1
#else
#define mcbsp_omap1() 0
#endif
#include <sound/dmaengine_pcm.h>
/* McBSP register numbers. Register address offset = num * reg_step */
enum
{
/* Common registers */
...
...
@@ -312,7 +312,8 @@ struct omap_mcbsp {
struct
omap_mcbsp_platform_data
*
pdata
;
struct
omap_mcbsp_st_data
*
st_data
;
struct
omap_mcbsp_reg_cfg
cfg_regs
;
struct
omap_pcm_dma_data
dma_data
[
2
];
struct
snd_dmaengine_dai_dma_data
dma_data
[
2
];
unsigned
int
dma_req
[
2
];
int
dma_op_mode
;
u16
max_tx_thres
;
u16
max_rx_thres
;
...
...
sound/soc/omap/n810.c
View file @
d45a26bd
...
...
@@ -34,7 +34,6 @@
#include <linux/platform_data/asoc-ti-mcbsp.h>
#include "omap-mcbsp.h"
#include "omap-pcm.h"
#define N810_HEADSET_AMP_GPIO 10
#define N810_SPEAKER_AMP_GPIO 101
...
...
sound/soc/omap/omap-abe-twl6040.c
View file @
d45a26bd
...
...
@@ -34,7 +34,6 @@
#include "omap-dmic.h"
#include "omap-mcpdm.h"
#include "omap-pcm.h"
#include "../codecs/twl6040.h"
struct
abe_twl6040
{
...
...
sound/soc/omap/omap-dmic.c
View file @
d45a26bd
...
...
@@ -39,8 +39,8 @@
#include <sound/pcm_params.h>
#include <sound/initval.h>
#include <sound/soc.h>
#include <sound/dmaengine_pcm.h>
#include "omap-pcm.h"
#include "omap-dmic.h"
struct
omap_dmic
{
...
...
@@ -55,13 +55,9 @@ struct omap_dmic {
u32
ch_enabled
;
bool
active
;
struct
mutex
mutex
;
};
/*
* Stream DMA parameters
*/
static
struct
omap_pcm_dma_data
omap_dmic_dai_dma_params
=
{
.
name
=
"DMIC capture"
,
struct
snd_dmaengine_dai_dma_data
dma_data
;
unsigned
int
dma_req
;
};
static
inline
void
omap_dmic_write
(
struct
omap_dmic
*
dmic
,
u16
reg
,
u32
val
)
...
...
@@ -118,7 +114,7 @@ static int omap_dmic_dai_startup(struct snd_pcm_substream *substream,
mutex_unlock
(
&
dmic
->
mutex
);
snd_soc_dai_set_dma_data
(
dai
,
substream
,
&
omap_dmic_dai_dma_params
);
snd_soc_dai_set_dma_data
(
dai
,
substream
,
&
dmic
->
dma_data
);
return
ret
;
}
...
...
@@ -203,7 +199,7 @@ static int omap_dmic_dai_hw_params(struct snd_pcm_substream *substream,
struct
snd_soc_dai
*
dai
)
{
struct
omap_dmic
*
dmic
=
snd_soc_dai_get_drvdata
(
dai
);
struct
omap_pcm
_dma_data
*
dma_data
;
struct
snd_dmaengine_dai
_dma_data
*
dma_data
;
int
channels
;
dmic
->
clk_div
=
omap_dmic_select_divider
(
dmic
,
params_rate
(
params
));
...
...
@@ -230,7 +226,7 @@ static int omap_dmic_dai_hw_params(struct snd_pcm_substream *substream,
/* packet size is threshold * channels */
dma_data
=
snd_soc_dai_get_dma_data
(
dai
,
substream
);
dma_data
->
packet_size
=
dmic
->
threshold
*
channels
;
dma_data
->
maxburst
=
dmic
->
threshold
*
channels
;
return
0
;
}
...
...
@@ -476,7 +472,7 @@ static int asoc_dmic_probe(struct platform_device *pdev)
ret
=
-
ENODEV
;
goto
err_put_clk
;
}
omap_dmic_dai_dma_params
.
port_
addr
=
res
->
start
+
OMAP_DMIC_DATA_REG
;
dmic
->
dma_data
.
addr
=
res
->
start
+
OMAP_DMIC_DATA_REG
;
res
=
platform_get_resource
(
pdev
,
IORESOURCE_DMA
,
0
);
if
(
!
res
)
{
...
...
@@ -484,7 +480,9 @@ static int asoc_dmic_probe(struct platform_device *pdev)
ret
=
-
ENODEV
;
goto
err_put_clk
;
}
omap_dmic_dai_dma_params
.
dma_req
=
res
->
start
;
dmic
->
dma_req
=
res
->
start
;
dmic
->
dma_data
.
filter_data
=
&
dmic
->
dma_req
;
res
=
platform_get_resource_byname
(
pdev
,
IORESOURCE_MEM
,
"mpu"
);
if
(
!
res
)
{
...
...
@@ -493,19 +491,9 @@ static int asoc_dmic_probe(struct platform_device *pdev)
goto
err_put_clk
;
}
if
(
!
devm_request_mem_region
(
&
pdev
->
dev
,
res
->
start
,
resource_size
(
res
),
pdev
->
name
))
{
dev_err
(
dmic
->
dev
,
"memory region already claimed
\n
"
);
ret
=
-
ENODEV
;
goto
err_put_clk
;
}
dmic
->
io_base
=
devm_ioremap
(
&
pdev
->
dev
,
res
->
start
,
resource_size
(
res
));
if
(
!
dmic
->
io_base
)
{
ret
=
-
ENOMEM
;
goto
err_put_clk
;
}
dmic
->
io_base
=
devm_ioremap_resource
(
&
pdev
->
dev
,
res
);
if
(
IS_ERR
(
dmic
->
io_base
))
return
PTR_ERR
(
dmic
->
io_base
);
ret
=
snd_soc_register_dai
(
&
pdev
->
dev
,
&
omap_dmic_dai
);
if
(
ret
)
...
...
sound/soc/omap/omap-hdmi.c
View file @
d45a26bd
...
...
@@ -32,15 +32,16 @@
#include <sound/soc.h>
#include <sound/asound.h>
#include <sound/asoundef.h>
#include <sound/dmaengine_pcm.h>
#include <video/omapdss.h>
#include "omap-pcm.h"
#include "omap-hdmi.h"
#define DRV_NAME "omap-hdmi-audio-dai"
struct
hdmi_priv
{
struct
omap_pcm_dma_data
dma_params
;
struct
snd_dmaengine_dai_dma_data
dma_data
;
unsigned
int
dma_req
;
struct
omap_dss_audio
dss_audio
;
struct
snd_aes_iec958
iec
;
struct
snd_cea_861_aud_if
cea
;
...
...
@@ -68,7 +69,7 @@ static int omap_hdmi_dai_startup(struct snd_pcm_substream *substream,
return
-
ENODEV
;
}
snd_soc_dai_set_dma_data
(
dai
,
substream
,
&
priv
->
dma_
params
);
snd_soc_dai_set_dma_data
(
dai
,
substream
,
&
priv
->
dma_
data
);
return
0
;
}
...
...
@@ -88,25 +89,20 @@ static int omap_hdmi_dai_hw_params(struct snd_pcm_substream *substream,
struct
hdmi_priv
*
priv
=
snd_soc_dai_get_drvdata
(
dai
);
struct
snd_aes_iec958
*
iec
=
&
priv
->
iec
;
struct
snd_cea_861_aud_if
*
cea
=
&
priv
->
cea
;
struct
omap_pcm_dma_data
*
dma_data
;
int
err
=
0
;
dma_data
=
snd_soc_dai_get_dma_data
(
dai
,
substream
);
switch
(
params_format
(
params
))
{
case
SNDRV_PCM_FORMAT_S16_LE
:
dma_data
->
packet_size
=
16
;
priv
->
dma_data
.
maxburst
=
16
;
break
;
case
SNDRV_PCM_FORMAT_S24_LE
:
dma_data
->
packet_size
=
32
;
priv
->
dma_data
.
maxburst
=
32
;
break
;
default:
dev_err
(
dai
->
dev
,
"format not supported!
\n
"
);
return
-
EINVAL
;
}
dma_data
->
data_type
=
32
;
/*
* fill the IEC-60958 channel status word
*/
...
...
@@ -283,8 +279,7 @@ static int omap_hdmi_probe(struct platform_device *pdev)
return
-
ENODEV
;
}
hdmi_data
->
dma_params
.
port_addr
=
hdmi_rsrc
->
start
+
OMAP_HDMI_AUDIO_DMA_PORT
;
hdmi_data
->
dma_data
.
addr
=
hdmi_rsrc
->
start
+
OMAP_HDMI_AUDIO_DMA_PORT
;
hdmi_rsrc
=
platform_get_resource
(
pdev
,
IORESOURCE_DMA
,
0
);
if
(
!
hdmi_rsrc
)
{
...
...
@@ -292,8 +287,9 @@ static int omap_hdmi_probe(struct platform_device *pdev)
return
-
ENODEV
;
}
hdmi_data
->
dma_params
.
dma_req
=
hdmi_rsrc
->
start
;
hdmi_data
->
dma_params
.
name
=
"HDMI playback"
;
hdmi_data
->
dma_req
=
hdmi_rsrc
->
start
;
hdmi_data
->
dma_data
.
filter_data
=
&
hdmi_data
->
dma_req
;
hdmi_data
->
dma_data
.
addr_width
=
DMA_SLAVE_BUSWIDTH_4_BYTES
;
/*
* TODO: We assume that there is only one DSS HDMI device. Future
...
...
sound/soc/omap/omap-mcbsp.c
View file @
d45a26bd
...
...
@@ -33,11 +33,11 @@
#include <sound/pcm_params.h>
#include <sound/initval.h>
#include <sound/soc.h>
#include <sound/dmaengine_pcm.h>
#include <linux/platform_data/asoc-ti-mcbsp.h>
#include "mcbsp.h"
#include "omap-mcbsp.h"
#include "omap-pcm.h"
#define OMAP_MCBSP_RATES (SNDRV_PCM_RATE_8000_96000)
...
...
@@ -62,24 +62,22 @@ enum {
* Stream DMA parameters. DMA request line and port address are set runtime
* since they are different between OMAP1 and later OMAPs
*/
static
void
omap_mcbsp_set_threshold
(
struct
snd_pcm_substream
*
substream
)
static
void
omap_mcbsp_set_threshold
(
struct
snd_pcm_substream
*
substream
,
unsigned
int
packet_size
)
{
struct
snd_soc_pcm_runtime
*
rtd
=
substream
->
private_data
;
struct
snd_soc_dai
*
cpu_dai
=
rtd
->
cpu_dai
;
struct
omap_mcbsp
*
mcbsp
=
snd_soc_dai_get_drvdata
(
cpu_dai
);
struct
omap_pcm_dma_data
*
dma_data
;
int
words
;
dma_data
=
snd_soc_dai_get_dma_data
(
rtd
->
cpu_dai
,
substream
);
/*
* Configure McBSP threshold based on either:
* packet_size, when the sDMA is in packet mode, or based on the
* period size in THRESHOLD mode, otherwise use McBSP threshold = 1
* for mono streams.
*/
if
(
dma_data
->
packet_size
)
words
=
dma_data
->
packet_size
;
if
(
packet_size
)
words
=
packet_size
;
else
words
=
1
;
...
...
@@ -226,7 +224,7 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
{
struct
omap_mcbsp
*
mcbsp
=
snd_soc_dai_get_drvdata
(
cpu_dai
);
struct
omap_mcbsp_reg_cfg
*
regs
=
&
mcbsp
->
cfg_regs
;
struct
omap_pcm
_dma_data
*
dma_data
;
struct
snd_dmaengine_dai
_dma_data
*
dma_data
;
int
wlen
,
channels
,
wpf
;
int
pkt_size
=
0
;
unsigned
int
format
,
div
,
framesize
,
master
;
...
...
@@ -245,7 +243,6 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
return
-
EINVAL
;
}
if
(
mcbsp
->
pdata
->
buffer_size
)
{
dma_data
->
set_threshold
=
omap_mcbsp_set_threshold
;
if
(
mcbsp
->
dma_op_mode
==
MCBSP_DMA_MODE_THRESHOLD
)
{
int
period_words
,
max_thrsh
;
int
divider
=
0
;
...
...
@@ -276,9 +273,10 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
/* Use packet mode for non mono streams */
pkt_size
=
channels
;
}
omap_mcbsp_set_threshold
(
substream
,
pkt_size
);
}
dma_data
->
packet_size
=
pkt_size
;
dma_data
->
maxburst
=
pkt_size
;
if
(
mcbsp
->
configured
)
{
/* McBSP already configured by another stream */
...
...
sound/soc/omap/omap-mcpdm.c
View file @
d45a26bd
...
...
@@ -39,11 +39,14 @@
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/dmaengine_pcm.h>
#include "omap-mcpdm.h"
#include "omap-pcm.h"
#define OMAP44XX_MCPDM_L3_BASE 0x49032000
struct
mcpdm_link_config
{
u32
link_mask
;
/* channel mask for the direction */
u32
threshold
;
/* FIFO threshold */
};
struct
omap_mcpdm
{
struct
device
*
dev
;
...
...
@@ -53,29 +56,22 @@ struct omap_mcpdm {
struct
mutex
mutex
;
/* channel data */
u32
dn_channels
;
u32
up_channels
;
/* McPDM FIFO thresholds */
u32
dn_threshold
;
u32
up_threshold
;
/* Playback/Capture configuration */
struct
mcpdm_link_config
config
[
2
];
/* McPDM dn offsets for rx1, and 2 channels */
u32
dn_rx_offset
;
/* McPDM needs to be restarted due to runtime reconfiguration */
bool
restart
;
struct
snd_dmaengine_dai_dma_data
dma_data
[
2
];
unsigned
int
dma_req
[
2
];
};
/*
* Stream DMA parameters
*/
static
struct
omap_pcm_dma_data
omap_mcpdm_dai_dma_params
[]
=
{
{
.
name
=
"Audio playback"
,
},
{
.
name
=
"Audio capture"
,
},
};
static
inline
void
omap_mcpdm_write
(
struct
omap_mcpdm
*
mcpdm
,
u16
reg
,
u32
val
)
{
...
...
@@ -130,11 +126,12 @@ static void omap_mcpdm_reg_dump(struct omap_mcpdm *mcpdm) {}
static
void
omap_mcpdm_start
(
struct
omap_mcpdm
*
mcpdm
)
{
u32
ctrl
=
omap_mcpdm_read
(
mcpdm
,
MCPDM_REG_CTRL
);
u32
link_mask
=
mcpdm
->
config
[
0
].
link_mask
|
mcpdm
->
config
[
1
].
link_mask
;
ctrl
|=
(
MCPDM_SW_DN_RST
|
MCPDM_SW_UP_RST
);
omap_mcpdm_write
(
mcpdm
,
MCPDM_REG_CTRL
,
ctrl
);
ctrl
|=
mcpdm
->
dn_channels
|
mcpdm
->
up_channels
;
ctrl
|=
link_mask
;
omap_mcpdm_write
(
mcpdm
,
MCPDM_REG_CTRL
,
ctrl
);
ctrl
&=
~
(
MCPDM_SW_DN_RST
|
MCPDM_SW_UP_RST
);
...
...
@@ -148,11 +145,12 @@ static void omap_mcpdm_start(struct omap_mcpdm *mcpdm)
static
void
omap_mcpdm_stop
(
struct
omap_mcpdm
*
mcpdm
)
{
u32
ctrl
=
omap_mcpdm_read
(
mcpdm
,
MCPDM_REG_CTRL
);
u32
link_mask
=
MCPDM_PDM_DN_MASK
|
MCPDM_PDM_UP_MASK
;
ctrl
|=
(
MCPDM_SW_DN_RST
|
MCPDM_SW_UP_RST
);
omap_mcpdm_write
(
mcpdm
,
MCPDM_REG_CTRL
,
ctrl
);
ctrl
&=
~
(
mcpdm
->
dn_channels
|
mcpdm
->
up_channels
);
ctrl
&=
~
(
link_mask
);
omap_mcpdm_write
(
mcpdm
,
MCPDM_REG_CTRL
,
ctrl
);
ctrl
&=
~
(
MCPDM_SW_DN_RST
|
MCPDM_SW_UP_RST
);
...
...
@@ -188,8 +186,10 @@ static void omap_mcpdm_open_streams(struct omap_mcpdm *mcpdm)
omap_mcpdm_write
(
mcpdm
,
MCPDM_REG_DN_OFFSET
,
dn_offset
);
}
omap_mcpdm_write
(
mcpdm
,
MCPDM_REG_FIFO_CTRL_DN
,
mcpdm
->
dn_threshold
);
omap_mcpdm_write
(
mcpdm
,
MCPDM_REG_FIFO_CTRL_UP
,
mcpdm
->
up_threshold
);
omap_mcpdm_write
(
mcpdm
,
MCPDM_REG_FIFO_CTRL_DN
,
mcpdm
->
config
[
SNDRV_PCM_STREAM_PLAYBACK
].
threshold
);
omap_mcpdm_write
(
mcpdm
,
MCPDM_REG_FIFO_CTRL_UP
,
mcpdm
->
config
[
SNDRV_PCM_STREAM_CAPTURE
].
threshold
);
omap_mcpdm_write
(
mcpdm
,
MCPDM_REG_DMAENABLE_SET
,
MCPDM_DMA_DN_ENABLE
|
MCPDM_DMA_UP_ENABLE
);
...
...
@@ -267,7 +267,7 @@ static int omap_mcpdm_dai_startup(struct snd_pcm_substream *substream,
mutex_unlock
(
&
mcpdm
->
mutex
);
snd_soc_dai_set_dma_data
(
dai
,
substream
,
&
omap_mcpdm_dai_dma_params
[
substream
->
stream
]);
&
mcpdm
->
dma_data
[
substream
->
stream
]);
return
0
;
}
...
...
@@ -283,6 +283,8 @@ static void omap_mcpdm_dai_shutdown(struct snd_pcm_substream *substream,
if
(
omap_mcpdm_active
(
mcpdm
))
{
omap_mcpdm_stop
(
mcpdm
);
omap_mcpdm_close_streams
(
mcpdm
);
mcpdm
->
config
[
0
].
link_mask
=
0
;
mcpdm
->
config
[
1
].
link_mask
=
0
;
}
}
...
...
@@ -295,7 +297,8 @@ static int omap_mcpdm_dai_hw_params(struct snd_pcm_substream *substream,
{
struct
omap_mcpdm
*
mcpdm
=
snd_soc_dai_get_drvdata
(
dai
);
int
stream
=
substream
->
stream
;
struct
omap_pcm_dma_data
*
dma_data
;
struct
snd_dmaengine_dai_dma_data
*
dma_data
;
u32
threshold
;
int
channels
;
int
link_mask
=
0
;
...
...
@@ -325,16 +328,32 @@ static int omap_mcpdm_dai_hw_params(struct snd_pcm_substream *substream,
dma_data
=
snd_soc_dai_get_dma_data
(
dai
,
substream
);
threshold
=
mcpdm
->
config
[
stream
].
threshold
;
/* Configure McPDM channels, and DMA packet size */
if
(
stream
==
SNDRV_PCM_STREAM_PLAYBACK
)
{
mcpdm
->
dn_channels
=
link_mask
<<
3
;
dma_data
->
packet_size
=
(
MCPDM_DN_THRES_MAX
-
mcpdm
->
dn_threshold
)
*
channels
;
link_mask
<<=
3
;
/* If capture is not running assume a stereo stream to come */
if
(
!
mcpdm
->
config
[
!
stream
].
link_mask
)
mcpdm
->
config
[
!
stream
].
link_mask
=
0x3
;
dma_data
->
maxburst
=
(
MCPDM_DN_THRES_MAX
-
threshold
)
*
channels
;
}
else
{
mcpdm
->
up_channels
=
link_mask
<<
0
;
dma_data
->
packet_size
=
mcpdm
->
up_threshold
*
channels
;
/* If playback is not running assume a stereo stream to come */
if
(
!
mcpdm
->
config
[
!
stream
].
link_mask
)
mcpdm
->
config
[
!
stream
].
link_mask
=
(
0x3
<<
3
);
dma_data
->
maxburst
=
threshold
*
channels
;
}
/* Check if we need to restart McPDM with this stream */
if
(
mcpdm
->
config
[
stream
].
link_mask
&&
mcpdm
->
config
[
stream
].
link_mask
!=
link_mask
)
mcpdm
->
restart
=
true
;
mcpdm
->
config
[
stream
].
link_mask
=
link_mask
;
return
0
;
}
...
...
@@ -346,6 +365,11 @@ static int omap_mcpdm_prepare(struct snd_pcm_substream *substream,
if
(
!
omap_mcpdm_active
(
mcpdm
))
{
omap_mcpdm_start
(
mcpdm
);
omap_mcpdm_reg_dump
(
mcpdm
);
}
else
if
(
mcpdm
->
restart
)
{
omap_mcpdm_stop
(
mcpdm
);
omap_mcpdm_start
(
mcpdm
);
mcpdm
->
restart
=
false
;
omap_mcpdm_reg_dump
(
mcpdm
);
}
return
0
;
...
...
@@ -369,7 +393,7 @@ static int omap_mcpdm_probe(struct snd_soc_dai *dai)
pm_runtime_get_sync
(
mcpdm
->
dev
);
omap_mcpdm_write
(
mcpdm
,
MCPDM_REG_CTRL
,
0x00
);
ret
=
request_irq
(
mcpdm
->
irq
,
omap_mcpdm_irq_handler
,
ret
=
devm_request_irq
(
mcpdm
->
dev
,
mcpdm
->
irq
,
omap_mcpdm_irq_handler
,
0
,
"McPDM"
,
(
void
*
)
mcpdm
);
pm_runtime_put_sync
(
mcpdm
->
dev
);
...
...
@@ -380,8 +404,9 @@ static int omap_mcpdm_probe(struct snd_soc_dai *dai)
}
/* Configure McPDM threshold values */
mcpdm
->
dn_threshold
=
2
;
mcpdm
->
up_threshold
=
MCPDM_UP_THRES_MAX
-
3
;
mcpdm
->
config
[
SNDRV_PCM_STREAM_PLAYBACK
].
threshold
=
2
;
mcpdm
->
config
[
SNDRV_PCM_STREAM_CAPTURE
].
threshold
=
MCPDM_UP_THRES_MAX
-
3
;
return
ret
;
}
...
...
@@ -389,7 +414,6 @@ static int omap_mcpdm_remove(struct snd_soc_dai *dai)
{
struct
omap_mcpdm
*
mcpdm
=
snd_soc_dai_get_drvdata
(
dai
);
free_irq
(
mcpdm
->
irq
,
(
void
*
)
mcpdm
);
pm_runtime_disable
(
mcpdm
->
dev
);
return
0
;
...
...
@@ -446,33 +470,30 @@ static int asoc_mcpdm_probe(struct platform_device *pdev)
if
(
res
==
NULL
)
return
-
ENOMEM
;
omap_mcpdm_dai_dma_params
[
0
].
port_
addr
=
res
->
start
+
MCPDM_REG_DN_DATA
;
omap_mcpdm_dai_dma_params
[
1
].
port_
addr
=
res
->
start
+
MCPDM_REG_UP_DATA
;
mcpdm
->
dma_data
[
0
].
addr
=
res
->
start
+
MCPDM_REG_DN_DATA
;
mcpdm
->
dma_data
[
1
].
addr
=
res
->
start
+
MCPDM_REG_UP_DATA
;
res
=
platform_get_resource_byname
(
pdev
,
IORESOURCE_DMA
,
"dn_link"
);
if
(
!
res
)
return
-
ENODEV
;
omap_mcpdm_dai_dma_params
[
0
].
dma_req
=
res
->
start
;
mcpdm
->
dma_req
[
0
]
=
res
->
start
;
mcpdm
->
dma_data
[
0
].
filter_data
=
&
mcpdm
->
dma_req
[
0
];
res
=
platform_get_resource_byname
(
pdev
,
IORESOURCE_DMA
,
"up_link"
);
if
(
!
res
)
return
-
ENODEV
;
omap_mcpdm_dai_dma_params
[
1
].
dma_req
=
res
->
start
;
mcpdm
->
dma_req
[
1
]
=
res
->
start
;
mcpdm
->
dma_data
[
1
].
filter_data
=
&
mcpdm
->
dma_req
[
1
];
res
=
platform_get_resource_byname
(
pdev
,
IORESOURCE_MEM
,
"mpu"
);
if
(
res
==
NULL
)
return
-
ENOMEM
;
if
(
!
devm_request_mem_region
(
&
pdev
->
dev
,
res
->
start
,
resource_size
(
res
),
"McPDM"
))
return
-
EBUSY
;
mcpdm
->
io_base
=
devm_ioremap
(
&
pdev
->
dev
,
res
->
start
,
resource_size
(
res
));
if
(
!
mcpdm
->
io_base
)
return
-
ENOMEM
;
mcpdm
->
io_base
=
devm_ioremap_resource
(
&
pdev
->
dev
,
res
);
if
(
IS_ERR
(
mcpdm
->
io_base
))
return
PTR_ERR
(
mcpdm
->
io_base
);
mcpdm
->
irq
=
platform_get_irq
(
pdev
,
0
);
if
(
mcpdm
->
irq
<
0
)
...
...
sound/soc/omap/omap-pcm.c
View file @
d45a26bd
...
...
@@ -32,8 +32,6 @@
#include <sound/dmaengine_pcm.h>
#include <sound/soc.h>
#include "omap-pcm.h"
#ifdef CONFIG_ARCH_OMAP1
#define pcm_omap1510() cpu_is_omap1510()
#else
...
...
@@ -56,25 +54,6 @@ static const struct snd_pcm_hardware omap_pcm_hardware = {
.
buffer_bytes_max
=
128
*
1024
,
};
static
int
omap_pcm_get_dma_buswidth
(
int
num_bits
)
{
int
buswidth
;
switch
(
num_bits
)
{
case
16
:
buswidth
=
DMA_SLAVE_BUSWIDTH_2_BYTES
;
break
;
case
32
:
buswidth
=
DMA_SLAVE_BUSWIDTH_4_BYTES
;
break
;
default:
buswidth
=
-
EINVAL
;
break
;
}
return
buswidth
;
}
/* this may get called several times by oss emulation */
static
int
omap_pcm_hw_params
(
struct
snd_pcm_substream
*
substream
,
struct
snd_pcm_hw_params
*
params
)
...
...
@@ -105,20 +84,9 @@ static int omap_pcm_hw_params(struct snd_pcm_substream *substream,
if
(
err
)
return
err
;
/* Override the *_dma addr_width if requested by the DAI driver */
if
(
dma_data
->
data_type
)
{
int
buswidth
=
omap_pcm_get_dma_buswidth
(
dma_data
->
data_type
);
if
(
substream
->
stream
==
SNDRV_PCM_STREAM_PLAYBACK
)
config
.
dst_addr_width
=
buswidth
;
else
config
.
src_addr_width
=
buswidth
;
}
config
.
src_addr
=
dma_data
->
port_addr
;
config
.
dst_addr
=
dma_data
->
port_addr
;
config
.
src_maxburst
=
dma_data
->
packet_size
;
config
.
dst_maxburst
=
dma_data
->
packet_size
;
snd_dmaengine_pcm_set_config_from_dai_data
(
substream
,
snd_soc_dai_get_dma_data
(
rtd
->
cpu_dai
,
substream
),
&
config
);
return
dmaengine_slave_config
(
chan
,
&
config
);
}
...
...
@@ -129,37 +97,6 @@ static int omap_pcm_hw_free(struct snd_pcm_substream *substream)
return
0
;
}
static
int
omap_pcm_trigger
(
struct
snd_pcm_substream
*
substream
,
int
cmd
)
{
struct
snd_soc_pcm_runtime
*
rtd
=
substream
->
private_data
;
struct
omap_pcm_dma_data
*
dma_data
;
int
ret
=
0
;
dma_data
=
snd_soc_dai_get_dma_data
(
rtd
->
cpu_dai
,
substream
);
switch
(
cmd
)
{
case
SNDRV_PCM_TRIGGER_START
:
case
SNDRV_PCM_TRIGGER_RESUME
:
case
SNDRV_PCM_TRIGGER_PAUSE_RELEASE
:
/* Configure McBSP internal buffer usage */
if
(
dma_data
->
set_threshold
)
dma_data
->
set_threshold
(
substream
);
break
;
case
SNDRV_PCM_TRIGGER_STOP
:
case
SNDRV_PCM_TRIGGER_SUSPEND
:
case
SNDRV_PCM_TRIGGER_PAUSE_PUSH
:
break
;
default:
ret
=
-
EINVAL
;
}
if
(
ret
==
0
)
ret
=
snd_dmaengine_pcm_trigger
(
substream
,
cmd
);
return
ret
;
}
static
snd_pcm_uframes_t
omap_pcm_pointer
(
struct
snd_pcm_substream
*
substream
)
{
snd_pcm_uframes_t
offset
;
...
...
@@ -175,20 +112,15 @@ static snd_pcm_uframes_t omap_pcm_pointer(struct snd_pcm_substream *substream)
static
int
omap_pcm_open
(
struct
snd_pcm_substream
*
substream
)
{
struct
snd_soc_pcm_runtime
*
rtd
=
substream
->
private_data
;
struct
omap_pcm
_dma_data
*
dma_data
;
struct
snd_dmaengine_dai
_dma_data
*
dma_data
;
snd_soc_set_runtime_hwparams
(
substream
,
&
omap_pcm_hardware
);
dma_data
=
snd_soc_dai_get_dma_data
(
rtd
->
cpu_dai
,
substream
);
return
snd_dmaengine_pcm_open
(
substream
,
omap_dma_filter_fn
,
&
dma_data
->
dma_req
);
}
static
int
omap_pcm_close
(
struct
snd_pcm_substream
*
substream
)
{
snd_dmaengine_pcm_close
(
substream
);
return
0
;
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
,
...
...
@@ -204,11 +136,11 @@ static int omap_pcm_mmap(struct snd_pcm_substream *substream,
static
struct
snd_pcm_ops
omap_pcm_ops
=
{
.
open
=
omap_pcm_open
,
.
close
=
omap_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
,
.
trigger
=
omap
_pcm_trigger
,
.
trigger
=
snd_dmaengine
_pcm_trigger
,
.
pointer
=
omap_pcm_pointer
,
.
mmap
=
omap_pcm_mmap
,
};
...
...
sound/soc/omap/omap-pcm.h
deleted
100644 → 0
View file @
8ef53f68
/*
* omap-pcm.h
*
* Copyright (C) 2008 Nokia Corporation
*
* Contact: Jarkko Nikula <jarkko.nikula@bitmer.com>
* Peter Ujfalusi <peter.ujfalusi@ti.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* 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., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA
*
*/
#ifndef __OMAP_PCM_H__
#define __OMAP_PCM_H__
struct
snd_pcm_substream
;
struct
omap_pcm_dma_data
{
char
*
name
;
/* stream identifier */
int
dma_req
;
/* DMA request line */
unsigned
long
port_addr
;
/* transmit/receive register */
void
(
*
set_threshold
)(
struct
snd_pcm_substream
*
substream
);
int
data_type
;
/* 8, 16, 32 (bits) or 0 to let omap-pcm
* to decide the sDMA data type */
int
packet_size
;
/* packet size only in PACKET mode */
};
#endif
sound/soc/omap/omap-twl4030.c
View file @
d45a26bd
...
...
@@ -43,7 +43,6 @@
#include <sound/jack.h>
#include "omap-mcbsp.h"
#include "omap-pcm.h"
struct
omap_twl4030
{
int
jack_detect
;
/* board can detect jack events */
...
...
sound/soc/omap/omap3pandora.c
View file @
d45a26bd
...
...
@@ -34,7 +34,6 @@
#include <linux/platform_data/asoc-ti-mcbsp.h>
#include "omap-mcbsp.h"
#include "omap-pcm.h"
#define OMAP3_PANDORA_DAC_POWER_GPIO 118
#define OMAP3_PANDORA_AMP_POWER_GPIO 14
...
...
@@ -80,12 +79,18 @@ static int omap3pandora_hw_params(struct snd_pcm_substream *substream,
static
int
omap3pandora_dac_event
(
struct
snd_soc_dapm_widget
*
w
,
struct
snd_kcontrol
*
k
,
int
event
)
{
int
ret
;
/*
* The PCM1773 DAC datasheet requires 1ms delay between switching
* VCC power on/off and /PD pin high/low
*/
if
(
SND_SOC_DAPM_EVENT_ON
(
event
))
{
regulator_enable
(
omap3pandora_dac_reg
);
ret
=
regulator_enable
(
omap3pandora_dac_reg
);
if
(
ret
)
{
dev_err
(
w
->
dapm
->
dev
,
"Failed to power DAC: %d
\n
"
,
ret
);
return
ret
;
}
mdelay
(
1
);
gpio_set_value
(
OMAP3_PANDORA_DAC_POWER_GPIO
,
1
);
}
else
{
...
...
sound/soc/omap/osk5912.c
View file @
d45a26bd
...
...
@@ -33,7 +33,6 @@
#include <linux/platform_data/asoc-ti-mcbsp.h>
#include "omap-mcbsp.h"
#include "omap-pcm.h"
#include "../codecs/tlv320aic23.h"
#define CODEC_CLOCK 12000000
...
...
sound/soc/omap/rx51.c
View file @
d45a26bd
...
...
@@ -37,7 +37,6 @@
#include <asm/mach-types.h>
#include "omap-mcbsp.h"
#include "omap-pcm.h"
#define RX51_TVOUT_SEL_GPIO 40
#define RX51_JACK_DETECT_GPIO 177
...
...
sound/soc/pxa/mmp-pcm.c
View file @
d45a26bd
...
...
@@ -118,9 +118,8 @@ static int mmp_pcm_open(struct snd_pcm_substream *substream)
struct
snd_soc_pcm_runtime
*
rtd
=
substream
->
private_data
;
struct
platform_device
*
pdev
=
to_platform_device
(
rtd
->
platform
->
dev
);
struct
snd_soc_dai
*
cpu_dai
=
rtd
->
cpu_dai
;
struct
mmp_dma_data
*
dma_data
;
struct
mmp_dma_data
dma_data
;
struct
resource
*
r
;
int
ret
;
r
=
platform_get_resource
(
pdev
,
IORESOURCE_DMA
,
substream
->
stream
);
if
(
!
r
)
...
...
@@ -128,33 +127,12 @@ static int mmp_pcm_open(struct snd_pcm_substream *substream)
snd_soc_set_runtime_hwparams
(
substream
,
&
mmp_pcm_hardware
[
substream
->
stream
]);
dma_data
=
devm_kzalloc
(
&
pdev
->
dev
,
sizeof
(
struct
mmp_dma_data
),
GFP_KERNEL
);
if
(
dma_data
==
NULL
)
return
-
ENOMEM
;
dma_data
->
dma_res
=
r
;
dma_data
->
ssp_id
=
cpu_dai
->
id
;
dma_data
.
dma_res
=
r
;
dma_data
.
ssp_id
=
cpu_dai
->
id
;
ret
=
snd_dmaengine_pcm_open
(
substream
,
filter
,
dma_data
);
if
(
ret
)
{
devm_kfree
(
&
pdev
->
dev
,
dma_data
);
return
ret
;
}
snd_dmaengine_pcm_set_data
(
substream
,
dma_data
);
return
0
;
}
static
int
mmp_pcm_close
(
struct
snd_pcm_substream
*
substream
)
{
struct
mmp_dma_data
*
dma_data
=
snd_dmaengine_pcm_get_data
(
substream
);
struct
snd_soc_pcm_runtime
*
rtd
=
substream
->
private_data
;
struct
platform_device
*
pdev
=
to_platform_device
(
rtd
->
platform
->
dev
);
snd_dmaengine_pcm_close
(
substream
);
devm_kfree
(
&
pdev
->
dev
,
dma_data
);
return
0
;
return
snd_dmaengine_pcm_open_request_chan
(
substream
,
filter
,
&
dma_data
);
}
static
int
mmp_pcm_mmap
(
struct
snd_pcm_substream
*
substream
,
...
...
@@ -171,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
=
mmp_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 @
d45a26bd
...
...
@@ -3903,21 +3903,14 @@ void snd_soc_unregister_dais(struct device *dev, size_t count)
EXPORT_SYMBOL_GPL
(
snd_soc_unregister_dais
);
/**
* 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
)
{
...
...
@@ -3940,30 +3933,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 @
d45a26bd
...
...
@@ -33,8 +33,6 @@ struct dmaengine_pcm_runtime_data {
dma_cookie_t
cookie
;
unsigned
int
pos
;
void
*
data
;
};
static
inline
struct
dmaengine_pcm_runtime_data
*
substream_to_prtd
(
...
...
@@ -43,33 +41,6 @@ static inline struct dmaengine_pcm_runtime_data *substream_to_prtd(
return
substream
->
runtime
->
private_data
;
}
/**
* snd_dmaengine_pcm_set_data - Set dmaengine substream private data
* @substream: PCM substream
* @data: Data to set
*/
void
snd_dmaengine_pcm_set_data
(
struct
snd_pcm_substream
*
substream
,
void
*
data
)
{
struct
dmaengine_pcm_runtime_data
*
prtd
=
substream_to_prtd
(
substream
);
prtd
->
data
=
data
;
}
EXPORT_SYMBOL_GPL
(
snd_dmaengine_pcm_set_data
);
/**
* snd_dmaengine_pcm_get_data - Get dmaeinge substream private data
* @substream: PCM substream
*
* Returns the data previously set with snd_dmaengine_pcm_set_data
*/
void
*
snd_dmaengine_pcm_get_data
(
struct
snd_pcm_substream
*
substream
)
{
struct
dmaengine_pcm_runtime_data
*
prtd
=
substream_to_prtd
(
substream
);
return
prtd
->
data
;
}
EXPORT_SYMBOL_GPL
(
snd_dmaengine_pcm_get_data
);
struct
dma_chan
*
snd_dmaengine_pcm_get_chan
(
struct
snd_pcm_substream
*
substream
)
{
struct
dmaengine_pcm_runtime_data
*
prtd
=
substream_to_prtd
(
substream
);
...
...
@@ -118,10 +89,49 @@ int snd_hwparams_to_dma_slave_config(const struct snd_pcm_substream *substream,
slave_config
->
src_addr_width
=
buswidth
;
}
slave_config
->
device_fc
=
false
;
return
0
;
}
EXPORT_SYMBOL_GPL
(
snd_hwparams_to_dma_slave_config
);
/**
* snd_dmaengine_pcm_set_config_from_dai_data() - Initializes a dma slave config
* using DAI DMA data.
* @substream: PCM substream
* @dma_data: DAI DMA data
* @slave_config: DMA slave configuration
*
* Initializes the {dst,src}_addr, {dst,src}_maxburst, {dst,src}_addr_width and
* slave_id fields of the DMA slave config from the same fields of the DAI DMA
* data struct. The src and dst fields will be initialized depending on the
* direction of the substream. If the substream is a playback stream the dst
* fields will be initialized, if it is a capture stream the src fields will be
* initialized. The {dst,src}_addr_width field will only be initialized if the
* addr_width field of the DAI DMA data struct is not equal to
* DMA_SLAVE_BUSWIDTH_UNDEFINED.
*/
void
snd_dmaengine_pcm_set_config_from_dai_data
(
const
struct
snd_pcm_substream
*
substream
,
const
struct
snd_dmaengine_dai_dma_data
*
dma_data
,
struct
dma_slave_config
*
slave_config
)
{
if
(
substream
->
stream
==
SNDRV_PCM_STREAM_PLAYBACK
)
{
slave_config
->
dst_addr
=
dma_data
->
addr
;
slave_config
->
dst_maxburst
=
dma_data
->
maxburst
;
if
(
dma_data
->
addr_width
!=
DMA_SLAVE_BUSWIDTH_UNDEFINED
)
slave_config
->
dst_addr_width
=
dma_data
->
addr_width
;
}
else
{
slave_config
->
src_addr
=
dma_data
->
addr
;
slave_config
->
src_maxburst
=
dma_data
->
maxburst
;
if
(
dma_data
->
addr_width
!=
DMA_SLAVE_BUSWIDTH_UNDEFINED
)
slave_config
->
src_addr_width
=
dma_data
->
addr_width
;
}
slave_config
->
slave_id
=
dma_data
->
slave_id
;
}
EXPORT_SYMBOL_GPL
(
snd_dmaengine_pcm_set_config_from_dai_data
);
static
void
dmaengine_pcm_dma_complete
(
void
*
arg
)
{
struct
snd_pcm_substream
*
substream
=
arg
;
...
...
@@ -244,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
)
...
...
@@ -291,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
;
...
...
@@ -303,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
...
...
@@ -311,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 @
d45a26bd
/*
* 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 <linux/of_dma.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
;
bool
compat
;
};
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
->
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
->
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"
,
};
/**
* 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
;
unsigned
int
i
;
pcm
=
kzalloc
(
sizeof
(
*
pcm
),
GFP_KERNEL
);
if
(
!
pcm
)
return
-
ENOMEM
;
pcm
->
config
=
config
;
if
(
flags
&
SND_DMAENGINE_PCM_FLAG_COMPAT
)
pcm
->
compat
=
true
;
if
(
!
(
flags
&
SND_DMAENGINE_PCM_FLAG_NO_DT
)
&&
dev
->
of_node
)
{
for
(
i
=
SNDRV_PCM_STREAM_PLAYBACK
;
i
<=
SNDRV_PCM_STREAM_CAPTURE
;
i
++
)
{
pcm
->
chan
[
i
]
=
of_dma_request_slave_channel
(
dev
->
of_node
,
dmaengine_pcm_dma_channel_names
[
i
]);
}
}
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
]);
}
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 @
d45a26bd
...
...
@@ -64,21 +64,8 @@ static int spear_pcm_open(struct snd_pcm_substream *substream)
if
(
ret
)
return
ret
;
ret
=
snd_dmaengine_pcm_open
(
substream
,
dma_data
->
filter
,
dma_data
);
if
(
ret
)
return
ret
;
snd_dmaengine_pcm_set_data
(
substream
,
dma_data
);
return
0
;
}
static
int
spear_pcm_close
(
struct
snd_pcm_substream
*
substream
)
{
snd_dmaengine_pcm_close
(
substream
);
return
0
;
return
snd_dmaengine_pcm_open_request_chan
(
substream
,
dma_data
->
filter
,
dma_data
);
}
static
int
spear_pcm_mmap
(
struct
snd_pcm_substream
*
substream
,
...
...
@@ -93,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
=
s
pear_pcm_close
,
.
close
=
s
nd_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 @
d45a26bd
...
...
@@ -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/tegra20_ac97.c
View file @
d45a26bd
...
...
@@ -35,6 +35,7 @@
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/dmaengine_pcm.h>
#include "tegra_asoc_utils.h"
#include "tegra20_ac97.h"
...
...
@@ -389,14 +390,14 @@ static int tegra20_ac97_platform_probe(struct platform_device *pdev)
}
ac97
->
capture_dma_data
.
addr
=
mem
->
start
+
TEGRA20_AC97_FIFO_RX1
;
ac97
->
capture_dma_data
.
wrap
=
4
;
ac97
->
capture_dma_data
.
width
=
32
;
ac97
->
capture_dma_data
.
req_sel
=
of_dma
[
1
];
ac97
->
capture_dma_data
.
addr_width
=
DMA_SLAVE_BUSWIDTH_4_BYTES
;
ac97
->
capture_dma_data
.
maxburst
=
4
;
ac97
->
capture_dma_data
.
slave_id
=
of_dma
[
1
];
ac97
->
playback_dma_data
.
addr
=
mem
->
start
+
TEGRA20_AC97_FIFO_TX1
;
ac97
->
playback_dma_data
.
wrap
=
4
;
ac97
->
playback_dma_data
.
width
=
32
;
ac97
->
playback_dma_data
.
req_sel
=
of_dma
[
1
];
ac97
->
capture_dma_data
.
addr_width
=
DMA_SLAVE_BUSWIDTH_4_BYTES
;
ac97
->
capture_dma_data
.
maxburst
=
4
;
ac97
->
capture_dma_data
.
slave_id
=
of_dma
[
0
];
ret
=
snd_soc_register_dais
(
&
pdev
->
dev
,
&
tegra20_ac97_dai
,
1
);
if
(
ret
)
{
...
...
sound/soc/tegra/tegra20_ac97.h
View file @
d45a26bd
...
...
@@ -85,8 +85,8 @@
struct
tegra20_ac97
{
struct
clk
*
clk_ac97
;
struct
tegra_pcm_dma_params
capture_dma_data
;
struct
tegra_pcm_dma_params
playback_dma_data
;
struct
snd_dmaengine_dai_dma_data
capture_dma_data
;
struct
snd_dmaengine_dai_dma_data
playback_dma_data
;
struct
regmap
*
regmap
;
int
reset_gpio
;
int
sync_gpio
;
...
...
sound/soc/tegra/tegra20_i2s.c
View file @
d45a26bd
...
...
@@ -41,6 +41,7 @@
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/dmaengine_pcm.h>
#include "tegra20_i2s.h"
...
...
@@ -403,14 +404,14 @@ static int tegra20_i2s_platform_probe(struct platform_device *pdev)
}
i2s
->
capture_dma_data
.
addr
=
mem
->
start
+
TEGRA20_I2S_FIFO2
;
i2s
->
capture_dma_data
.
wrap
=
4
;
i2s
->
capture_dma_data
.
width
=
32
;
i2s
->
capture_dma_data
.
req_sel
=
dma_ch
;
i2s
->
capture_dma_data
.
addr_width
=
DMA_SLAVE_BUSWIDTH_4_BYTES
;
i2s
->
capture_dma_data
.
maxburst
=
4
;
i2s
->
capture_dma_data
.
slave_id
=
dma_ch
;
i2s
->
playback_dma_data
.
addr
=
mem
->
start
+
TEGRA20_I2S_FIFO1
;
i2s
->
playback_dma_data
.
wrap
=
4
;
i2s
->
playback_dma_data
.
width
=
32
;
i2s
->
playback_dma_data
.
req_sel
=
dma_ch
;
i2s
->
playback_dma_data
.
addr_width
=
DMA_SLAVE_BUSWIDTH_4_BYTES
;
i2s
->
playback_dma_data
.
maxburst
=
4
;
i2s
->
playback_dma_data
.
slave_id
=
dma_ch
;
pm_runtime_enable
(
&
pdev
->
dev
);
if
(
!
pm_runtime_enabled
(
&
pdev
->
dev
))
{
...
...
sound/soc/tegra/tegra20_i2s.h
View file @
d45a26bd
...
...
@@ -155,8 +155,8 @@
struct
tegra20_i2s
{
struct
snd_soc_dai_driver
dai
;
struct
clk
*
clk_i2s
;
struct
tegra_pcm_dma_params
capture_dma_data
;
struct
tegra_pcm_dma_params
playback_dma_data
;
struct
snd_dmaengine_dai_dma_data
capture_dma_data
;
struct
snd_dmaengine_dai_dma_data
playback_dma_data
;
struct
regmap
*
regmap
;
};
...
...
sound/soc/tegra/tegra20_spdif.c
View file @
d45a26bd
...
...
@@ -32,6 +32,7 @@
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/dmaengine_pcm.h>
#include "tegra20_spdif.h"
...
...
@@ -318,9 +319,9 @@ static int tegra20_spdif_platform_probe(struct platform_device *pdev)
}
spdif
->
playback_dma_data
.
addr
=
mem
->
start
+
TEGRA20_SPDIF_DATA_OUT
;
spdif
->
playback_dma_data
.
wrap
=
4
;
spdif
->
playback_dma_data
.
width
=
32
;
spdif
->
playback_dma_data
.
req_sel
=
dmareq
->
start
;
spdif
->
capture_dma_data
.
addr_width
=
DMA_SLAVE_BUSWIDTH_4_BYTES
;
spdif
->
capture_dma_data
.
maxburst
=
4
;
spdif
->
playback_dma_data
.
slave_id
=
dmareq
->
start
;
pm_runtime_enable
(
&
pdev
->
dev
);
if
(
!
pm_runtime_enabled
(
&
pdev
->
dev
))
{
...
...
sound/soc/tegra/tegra20_spdif.h
View file @
d45a26bd
...
...
@@ -462,8 +462,8 @@
struct
tegra20_spdif
{
struct
clk
*
clk_spdif_out
;
struct
tegra_pcm_dma_params
capture_dma_data
;
struct
tegra_pcm_dma_params
playback_dma_data
;
struct
snd_dmaengine_dai_dma_data
capture_dma_data
;
struct
snd_dmaengine_dai_dma_data
playback_dma_data
;
struct
regmap
*
regmap
;
};
...
...
sound/soc/tegra/tegra30_ahub.c
View file @
d45a26bd
...
...
@@ -95,8 +95,8 @@ static int tegra30_ahub_runtime_resume(struct device *dev)
}
int
tegra30_ahub_allocate_rx_fifo
(
enum
tegra30_ahub_rxcif
*
rxcif
,
unsigned
long
*
fiforeg
,
unsigned
long
*
reqsel
)
dma_addr_t
*
fiforeg
,
unsigned
int
*
reqsel
)
{
int
channel
;
u32
reg
,
val
;
...
...
@@ -178,8 +178,8 @@ int tegra30_ahub_free_rx_fifo(enum tegra30_ahub_rxcif rxcif)
EXPORT_SYMBOL_GPL
(
tegra30_ahub_free_rx_fifo
);
int
tegra30_ahub_allocate_tx_fifo
(
enum
tegra30_ahub_txcif
*
txcif
,
unsigned
long
*
fiforeg
,
unsigned
long
*
reqsel
)
dma_addr_t
*
fiforeg
,
unsigned
int
*
reqsel
)
{
int
channel
;
u32
reg
,
val
;
...
...
sound/soc/tegra/tegra30_ahub.h
View file @
d45a26bd
...
...
@@ -451,15 +451,15 @@ enum tegra30_ahub_rxcif {
};
extern
int
tegra30_ahub_allocate_rx_fifo
(
enum
tegra30_ahub_rxcif
*
rxcif
,
unsigned
long
*
fiforeg
,
unsigned
long
*
reqsel
);
dma_addr_t
*
fiforeg
,
unsigned
int
*
reqsel
);
extern
int
tegra30_ahub_enable_rx_fifo
(
enum
tegra30_ahub_rxcif
rxcif
);
extern
int
tegra30_ahub_disable_rx_fifo
(
enum
tegra30_ahub_rxcif
rxcif
);
extern
int
tegra30_ahub_free_rx_fifo
(
enum
tegra30_ahub_rxcif
rxcif
);
extern
int
tegra30_ahub_allocate_tx_fifo
(
enum
tegra30_ahub_txcif
*
txcif
,
unsigned
long
*
fiforeg
,
unsigned
long
*
reqsel
);
dma_addr_t
*
fiforeg
,
unsigned
int
*
reqsel
);
extern
int
tegra30_ahub_enable_tx_fifo
(
enum
tegra30_ahub_txcif
txcif
);
extern
int
tegra30_ahub_disable_tx_fifo
(
enum
tegra30_ahub_txcif
txcif
);
extern
int
tegra30_ahub_free_tx_fifo
(
enum
tegra30_ahub_txcif
txcif
);
...
...
sound/soc/tegra/tegra30_i2s.c
View file @
d45a26bd
...
...
@@ -38,6 +38,7 @@
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/dmaengine_pcm.h>
#include "tegra30_ahub.h"
#include "tegra30_i2s.h"
...
...
@@ -80,17 +81,17 @@ static int tegra30_i2s_startup(struct snd_pcm_substream *substream,
if
(
substream
->
stream
==
SNDRV_PCM_STREAM_PLAYBACK
)
{
ret
=
tegra30_ahub_allocate_tx_fifo
(
&
i2s
->
playback_fifo_cif
,
&
i2s
->
playback_dma_data
.
addr
,
&
i2s
->
playback_dma_data
.
req_sel
);
i2s
->
playback_dma_data
.
wrap
=
4
;
i2s
->
playback_dma_data
.
width
=
32
;
&
i2s
->
playback_dma_data
.
slave_id
);
i2s
->
playback_dma_data
.
addr_width
=
DMA_SLAVE_BUSWIDTH_4_BYTES
;
i2s
->
playback_dma_data
.
maxburst
=
4
;
tegra30_ahub_set_rx_cif_source
(
i2s
->
playback_i2s_cif
,
i2s
->
playback_fifo_cif
);
}
else
{
ret
=
tegra30_ahub_allocate_rx_fifo
(
&
i2s
->
capture_fifo_cif
,
&
i2s
->
capture_dma_data
.
addr
,
&
i2s
->
capture_dma_data
.
req_sel
);
i2s
->
capture_dma_data
.
wrap
=
4
;
i2s
->
capture_dma_data
.
width
=
32
;
&
i2s
->
capture_dma_data
.
slave_id
);
i2s
->
capture_dma_data
.
addr_width
=
DMA_SLAVE_BUSWIDTH_4_BYTES
;
i2s
->
capture_dma_data
.
maxburst
=
4
;
tegra30_ahub_set_rx_cif_source
(
i2s
->
capture_fifo_cif
,
i2s
->
capture_i2s_cif
);
}
...
...
sound/soc/tegra/tegra30_i2s.h
View file @
d45a26bd
...
...
@@ -231,10 +231,10 @@ struct tegra30_i2s {
struct
clk
*
clk_i2s
;
enum
tegra30_ahub_txcif
capture_i2s_cif
;
enum
tegra30_ahub_rxcif
capture_fifo_cif
;
struct
tegra_pcm_dma_params
capture_dma_data
;
struct
snd_dmaengine_dai_dma_data
capture_dma_data
;
enum
tegra30_ahub_rxcif
playback_i2s_cif
;
enum
tegra30_ahub_txcif
playback_fifo_cif
;
struct
tegra_pcm_dma_params
playback_dma_data
;
struct
snd_dmaengine_dai_dma_data
playback_dma_data
;
struct
regmap
*
regmap
;
};
...
...
sound/soc/tegra/tegra_pcm.c
View file @
d45a26bd
...
...
@@ -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,191 +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_close
(
struct
snd_pcm_substream
*
substream
)
{
snd_dmaengine_pcm_close
(
substream
);
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
tegra_pcm_dma_params
*
dmap
;
struct
dma_slave_config
slave_config
;
int
ret
;
dmap
=
snd_soc_dai_get_dma_data
(
rtd
->
cpu_dai
,
substream
);
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
;
}
if
(
substream
->
stream
==
SNDRV_PCM_STREAM_PLAYBACK
)
{
slave_config
.
dst_addr_width
=
DMA_SLAVE_BUSWIDTH_4_BYTES
;
slave_config
.
dst_addr
=
dmap
->
addr
;
slave_config
.
dst_maxburst
=
4
;
}
else
{
slave_config
.
src_addr_width
=
DMA_SLAVE_BUSWIDTH_4_BYTES
;
slave_config
.
src_addr
=
dmap
->
addr
;
slave_config
.
src_maxburst
=
4
;
}
slave_config
.
slave_id
=
dmap
->
req_sel
;
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
=
tegra_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/tegra/tegra_pcm.h
View file @
d45a26bd
...
...
@@ -31,13 +31,6 @@
#ifndef __TEGRA_PCM_H__
#define __TEGRA_PCM_H__
struct
tegra_pcm_dma_params
{
unsigned
long
addr
;
unsigned
long
wrap
;
unsigned
long
width
;
unsigned
long
req_sel
;
};
int
tegra_pcm_platform_register
(
struct
device
*
dev
);
void
tegra_pcm_platform_unregister
(
struct
device
*
dev
);
...
...
sound/soc/ux500/Kconfig
View file @
d45a26bd
...
...
@@ -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 @
d45a26bd
...
...
@@ -28,28 +28,19 @@
#include "ux500_msp_i2s.h"
#include "ux500_pcm.h"
static
struct
snd_pcm_hardware
ux500_pcm_hw_playback
=
{
.
info
=
SNDRV_PCM_INFO_INTERLEAVED
|
SNDRV_PCM_INFO_MMAP
|
SNDRV_PCM_INFO_RESUME
|
SNDRV_PCM_INFO_PAUSE
,
.
formats
=
SNDRV_PCM_FMTBIT_S16_LE
|
SNDRV_PCM_FMTBIT_U16_LE
|
SNDRV_PCM_FMTBIT_S16_BE
|
SNDRV_PCM_FMTBIT_U16_BE
,
.
rates
=
SNDRV_PCM_RATE_KNOT
,
.
rate_min
=
UX500_PLATFORM_MIN_RATE_PLAYBACK
,
.
rate_max
=
UX500_PLATFORM_MAX_RATE_PLAYBACK
,
.
channels_min
=
UX500_PLATFORM_MIN_CHANNELS
,
.
channels_max
=
UX500_PLATFORM_MAX_CHANNELS
,
.
buffer_bytes_max
=
UX500_PLATFORM_BUFFER_BYTES_MAX
,
.
period_bytes_min
=
UX500_PLATFORM_PERIODS_BYTES_MIN
,
.
period_bytes_max
=
UX500_PLATFORM_PERIODS_BYTES_MAX
,
.
periods_min
=
UX500_PLATFORM_PERIODS_MIN
,
.
periods_max
=
UX500_PLATFORM_PERIODS_MAX
,
};
#define UX500_PLATFORM_MIN_RATE 8000
#define UX500_PLATFORM_MAX_RATE 48000
#define UX500_PLATFORM_MIN_CHANNELS 1
#define UX500_PLATFORM_MAX_CHANNELS 8
static
struct
snd_pcm_hardware
ux500_pcm_hw_capture
=
{
#define UX500_PLATFORM_PERIODS_BYTES_MIN 128
#define UX500_PLATFORM_PERIODS_BYTES_MAX (64 * PAGE_SIZE)
#define UX500_PLATFORM_PERIODS_MIN 2
#define UX500_PLATFORM_PERIODS_MAX 48
#define UX500_PLATFORM_BUFFER_BYTES_MAX (2048 * PAGE_SIZE)
static
const
struct
snd_pcm_hardware
ux500_pcm_hw
=
{
.
info
=
SNDRV_PCM_INFO_INTERLEAVED
|
SNDRV_PCM_INFO_MMAP
|
SNDRV_PCM_INFO_RESUME
|
...
...
@@ -59,8 +50,8 @@ static struct snd_pcm_hardware ux500_pcm_hw_capture = {
SNDRV_PCM_FMTBIT_S16_BE
|
SNDRV_PCM_FMTBIT_U16_BE
,
.
rates
=
SNDRV_PCM_RATE_KNOT
,
.
rate_min
=
UX500_PLATFORM_MIN_RATE
_CAPTURE
,
.
rate_max
=
UX500_PLATFORM_MAX_RATE
_CAPTURE
,
.
rate_min
=
UX500_PLATFORM_MIN_RATE
,
.
rate_max
=
UX500_PLATFORM_MAX_RATE
,
.
channels_min
=
UX500_PLATFORM_MIN_CHANNELS
,
.
channels_max
=
UX500_PLATFORM_MAX_CHANNELS
,
.
buffer_bytes_max
=
UX500_PLATFORM_BUFFER_BYTES_MAX
,
...
...
@@ -70,64 +61,23 @@ static struct snd_pcm_hardware ux500_pcm_hw_capture = {
.
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
)
{
int
stream_id
=
substream
->
pstr
->
stream
;
struct
snd_pcm_runtime
*
runtime
=
substream
->
runtime
;
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
));
dev_dbg
(
dev
,
"%s: Set runtime hwparams.
\n
"
,
__func__
);
if
(
stream_id
==
SNDRV_PCM_STREAM_PLAYBACK
)
snd_soc_set_runtime_hwparams
(
substream
,
&
ux500_pcm_hw_playback
);
else
snd_soc_set_runtime_hwparams
(
substream
,
&
ux500_pcm_hw_capture
);
/* ensure that buffer size is a multiple of period size */
ret
=
snd_pcm_hw_constraint_integer
(
runtime
,
SNDRV_PCM_HW_PARAM_PERIODS
);
if
(
ret
<
0
)
{
dev_err
(
dev
,
"%s: Error: snd_pcm_hw_constraints failed (%d)
\n
"
,
__func__
,
ret
);
return
ret
;
}
dev_dbg
(
dev
,
"%s: Set hw-struct for %s.
\n
"
,
__func__
,
snd_pcm_stream_str
(
substream
));
runtime
->
hw
=
(
stream_id
==
SNDRV_PCM_STREAM_PLAYBACK
)
?
ux500_pcm_hw_playback
:
ux500_pcm_hw_capture
;
dma_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
;
...
...
@@ -140,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
;
...
...
@@ -155,137 +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
;
}
snd_dmaengine_pcm_set_data
(
substream
,
dma_cfg
);
return
0
;
}
static
int
ux500_pcm_close
(
struct
snd_pcm_substream
*
substream
)
{
struct
snd_soc_pcm_runtime
*
rtd
=
substream
->
private_data
;
struct
snd_soc_dai
*
dai
=
rtd
->
cpu_dai
;
dev_dbg
(
dai
->
dev
,
"%s: Enter
\n
"
,
__func__
);
snd_dmaengine_pcm_close
(
substream
);
return
0
;
}
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
;
return
snd_dmaengine_pcm_request_channel
(
stedma40_filter
,
dma_cfg
);
}
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
=
ux500_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
"
,
...
...
@@ -299,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
);
sound/soc/ux500/ux500_pcm.h
View file @
d45a26bd
...
...
@@ -18,20 +18,6 @@
#include <linux/workqueue.h>
#define UX500_PLATFORM_MIN_RATE_PLAYBACK 8000
#define UX500_PLATFORM_MAX_RATE_PLAYBACK 48000
#define UX500_PLATFORM_MIN_RATE_CAPTURE 8000
#define UX500_PLATFORM_MAX_RATE_CAPTURE 48000
#define UX500_PLATFORM_MIN_CHANNELS 1
#define UX500_PLATFORM_MAX_CHANNELS 8
#define UX500_PLATFORM_PERIODS_BYTES_MIN 128
#define UX500_PLATFORM_PERIODS_BYTES_MAX (64 * PAGE_SIZE)
#define UX500_PLATFORM_PERIODS_MIN 2
#define UX500_PLATFORM_PERIODS_MAX 48
#define UX500_PLATFORM_BUFFER_BYTES_MAX (2048 * PAGE_SIZE)
int
ux500_pcm_register_platform
(
struct
platform_device
*
pdev
);
int
ux500_pcm_unregister_platform
(
struct
platform_device
*
pdev
);
...
...
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