Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
raspberrypi-kernel
提交
d45a26bd
R
raspberrypi-kernel
项目概览
openeuler
/
raspberrypi-kernel
通知
13
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
raspberrypi-kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
d45a26bd
编写于
4月 18, 2013
作者:
M
Mark Brown
浏览文件
操作
浏览文件
下载
差异文件
Merge remote-tracking branch 'asoc/topic/dma' into asoc-next
上级
8ef53f68
22f38f79
变更
60
隐藏空白更改
内联
并排
Showing
60 changed file
with
900 addition
and
1083 deletion
+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
未找到文件。
include/sound/dmaengine_pcm.h
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
已删除
100644 → 0
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
已删除
100644 → 0
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录