Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
Kernel
提交
2944c2f5
K
Kernel
项目概览
openeuler
/
Kernel
1 年多 前同步成功
通知
8
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
K
Kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
2944c2f5
编写于
2月 11, 2013
作者:
M
Mark Brown
浏览文件
操作
浏览文件
下载
差异文件
Merge remote-tracking branch 'asoc/topic/samsung' into asoc-next
上级
f8843c91
5b1d3c34
变更
16
隐藏空白更改
内联
并排
Showing
16 changed file
with
438 addition
and
129 deletion
+438
-129
Documentation/devicetree/bindings/sound/samsung,smdk-wm8994.txt
...ntation/devicetree/bindings/sound/samsung,smdk-wm8994.txt
+14
-0
Documentation/devicetree/bindings/sound/samsung-i2s.txt
Documentation/devicetree/bindings/sound/samsung-i2s.txt
+63
-0
arch/arm/boot/dts/exynos5250-smdk5250.dts
arch/arm/boot/dts/exynos5250-smdk5250.dts
+26
-0
arch/arm/boot/dts/exynos5250.dtsi
arch/arm/boot/dts/exynos5250.dtsi
+38
-6
arch/arm/mach-exynos/mach-exynos5-dt.c
arch/arm/mach-exynos/mach-exynos5-dt.c
+6
-0
arch/arm/plat-samsung/dma-ops.c
arch/arm/plat-samsung/dma-ops.c
+8
-2
arch/arm/plat-samsung/include/plat/dma-ops.h
arch/arm/plat-samsung/include/plat/dma-ops.h
+2
-1
arch/arm/plat-samsung/s3c-dma-ops.c
arch/arm/plat-samsung/s3c-dma-ops.c
+2
-1
drivers/spi/spi-s3c64xx.c
drivers/spi/spi-s3c64xx.c
+23
-54
sound/soc/samsung/Kconfig
sound/soc/samsung/Kconfig
+3
-3
sound/soc/samsung/dma.c
sound/soc/samsung/dma.c
+2
-1
sound/soc/samsung/dma.h
sound/soc/samsung/dma.h
+1
-0
sound/soc/samsung/i2s.c
sound/soc/samsung/i2s.c
+220
-47
sound/soc/samsung/i2s.h
sound/soc/samsung/i2s.h
+0
-7
sound/soc/samsung/smdk_wm8580.c
sound/soc/samsung/smdk_wm8580.c
+2
-5
sound/soc/samsung/smdk_wm8994.c
sound/soc/samsung/smdk_wm8994.c
+28
-2
未找到文件。
Documentation/devicetree/bindings/sound/samsung,smdk-wm8994.txt
0 → 100644
浏览文件 @
2944c2f5
Samsung SMDK audio complex
Required properties:
- compatible : "samsung,smdk-wm8994"
- samsung,i2s-controller: The phandle of the Samsung I2S0 controller
- samsung,audio-codec: The phandle of the WM8994 audio codec
Example:
sound {
compatible = "samsung,smdk-wm8994";
samsung,i2s-controller = <&i2s0>;
samsung,audio-codec = <&wm8994>;
};
Documentation/devicetree/bindings/sound/samsung-i2s.txt
0 → 100644
浏览文件 @
2944c2f5
* Samsung I2S controller
Required SoC Specific Properties:
- compatible : "samsung,i2s-v5"
- reg: physical base address of the controller and length of memory mapped
region.
- dmas: list of DMA controller phandle and DMA request line ordered pairs.
- dma-names: identifier string for each DMA request line in the dmas property.
These strings correspond 1:1 with the ordered pairs in dmas.
Optional SoC Specific Properties:
- samsung,supports-6ch: If the I2S Primary sound source has 5.1 Channel
support, this flag is enabled.
- samsung,supports-rstclr: This flag should be set if I2S software reset bit
control is required. When this flag is set I2S software reset bit will be
enabled or disabled based on need.
- samsung,supports-secdai:If I2S block has a secondary FIFO and internal DMA,
then this flag is enabled.
- samsung,idma-addr: Internal DMA register base address of the audio
sub system(used in secondary sound source).
Required Board Specific Properties:
- gpios: The gpio specifier for data out,data in, LRCLK, CDCLK and SCLK
interface lines. The format of the gpio specifier depends on the gpio
controller.
The syntax of samsung gpio specifier is
<[phandle of the gpio controller node]
[pin number within the gpio controller]
[mux function]
[flags and pull up/down]
[drive strength]>
Example:
- SoC Specific Portion:
i2s@03830000 {
compatible = "samsung,i2s-v5";
reg = <0x03830000 0x100>;
dmas = <&pdma0 10
&pdma0 9
&pdma0 8>;
dma-names = "tx", "rx", "tx-sec";
samsung,supports-6ch;
samsung,supports-rstclr;
samsung,supports-secdai;
samsung,idma-addr = <0x03000000>;
};
- Board Specific Portion:
i2s@03830000 {
gpios = <&gpz 0 2 0 0>, /* I2S_0_SCLK */
<&gpz 1 2 0 0>, /* I2S_0_CDCLK */
<&gpz 2 2 0 0>, /* I2S_0_LRCK */
<&gpz 3 2 0 0>, /* I2S_0_SDI */
<&gpz 4 2 0 0>, /* I2S_0_SDO[1] */
<&gpz 5 2 0 0>, /* I2S_0_SDO[2] */
<&gpz 6 2 0 0>; /* I2S_0_SDO[3] */
};
arch/arm/boot/dts/exynos5250-smdk5250.dts
浏览文件 @
2944c2f5
...
...
@@ -49,6 +49,11 @@
compatible
=
"samsung,s524ad0xd1"
;
reg
=
<
0x51
>;
};
wm8994
:
wm8994
@
1
a
{
compatible
=
"wlf,wm8994"
;
reg
=
<
0x1a
>;
};
};
i2c
@
121
D0000
{
...
...
@@ -204,4 +209,25 @@
samsung
,
mfc
-
r
=
<
0x43000000
0x800000
>;
samsung
,
mfc
-
l
=
<
0x51000000
0x800000
>;
};
i2s0
:
i2s
@
03830000
{
gpios
=
<&
gpz
0
2
0
0
>,
<&
gpz
1
2
0
0
>,
<&
gpz
2
2
0
0
>,
<&
gpz
3
2
0
0
>,
<&
gpz
4
2
0
0
>,
<&
gpz
5
2
0
0
>,
<&
gpz
6
2
0
0
>;
};
i2s1
:
i2s
@
12
D60000
{
status
=
"disabled"
;
};
i2s2
:
i2s
@
12
D70000
{
status
=
"disabled"
;
};
sound
{
compatible
=
"samsung,smdk-wm8994"
;
samsung
,
i2s
-
controller
=
<&
i2s0
>;
samsung
,
audio
-
codec
=
<&
wm8994
>;
};
};
arch/arm/boot/dts/exynos5250.dtsi
浏览文件 @
2944c2f5
...
...
@@ -211,8 +211,9 @@
compatible = "samsung,exynos4210-spi";
reg = <0x12d20000 0x100>;
interrupts = <0 66 0>;
tx-dma-channel = <&pdma0 5>; /* preliminary */
rx-dma-channel = <&pdma0 4>; /* preliminary */
dmas = <&pdma0 5
&pdma0 4>;
dma-names = "tx", "rx";
#address-cells = <1>;
#size-cells = <0>;
};
...
...
@@ -221,8 +222,9 @@
compatible = "samsung,exynos4210-spi";
reg = <0x12d30000 0x100>;
interrupts = <0 67 0>;
tx-dma-channel = <&pdma1 5>; /* preliminary */
rx-dma-channel = <&pdma1 4>; /* preliminary */
dmas = <&pdma1 5
&pdma1 4>;
dma-names = "tx", "rx";
#address-cells = <1>;
#size-cells = <0>;
};
...
...
@@ -231,8 +233,9 @@
compatible = "samsung,exynos4210-spi";
reg = <0x12d40000 0x100>;
interrupts = <0 68 0>;
tx-dma-channel = <&pdma0 7>; /* preliminary */
rx-dma-channel = <&pdma0 6>; /* preliminary */
dmas = <&pdma0 7
&pdma0 6>;
dma-names = "tx", "rx";
#address-cells = <1>;
#size-cells = <0>;
};
...
...
@@ -269,6 +272,35 @@
#size-cells = <0>;
};
i2s0: i2s@03830000 {
compatible = "samsung,i2s-v5";
reg = <0x03830000 0x100>;
dmas = <&pdma0 10
&pdma0 9
&pdma0 8>;
dma-names = "tx", "rx", "tx-sec";
samsung,supports-6ch;
samsung,supports-rstclr;
samsung,supports-secdai;
samsung,idma-addr = <0x03000000>;
};
i2s1: i2s@12D60000 {
compatible = "samsung,i2s-v5";
reg = <0x12D60000 0x100>;
dmas = <&pdma1 12
&pdma1 11>;
dma-names = "tx", "rx";
};
i2s2: i2s@12D70000 {
compatible = "samsung,i2s-v5";
reg = <0x12D70000 0x100>;
dmas = <&pdma0 12
&pdma0 11>;
dma-names = "tx", "rx";
};
amba {
#address-cells = <1>;
#size-cells = <1>;
...
...
arch/arm/mach-exynos/mach-exynos5-dt.c
浏览文件 @
2944c2f5
...
...
@@ -104,6 +104,12 @@ static const struct of_dev_auxdata exynos5250_auxdata_lookup[] __initconst = {
OF_DEV_AUXDATA
(
"samsung,mfc-v6"
,
0x11000000
,
"s5p-mfc-v6"
,
NULL
),
OF_DEV_AUXDATA
(
"samsung,exynos5250-tmu"
,
0x10060000
,
"exynos-tmu"
,
NULL
),
OF_DEV_AUXDATA
(
"samsung,i2s-v5"
,
0x03830000
,
"samsung-i2s.0"
,
NULL
),
OF_DEV_AUXDATA
(
"samsung,i2s-v5"
,
0x12D60000
,
"samsung-i2s.1"
,
NULL
),
OF_DEV_AUXDATA
(
"samsung,i2s-v5"
,
0x12D70000
,
"samsung-i2s.2"
,
NULL
),
{},
};
...
...
arch/arm/plat-samsung/dma-ops.c
浏览文件 @
2944c2f5
...
...
@@ -19,7 +19,8 @@
#include <mach/dma.h>
static
unsigned
samsung_dmadev_request
(
enum
dma_ch
dma_ch
,
struct
samsung_dma_req
*
param
)
struct
samsung_dma_req
*
param
,
struct
device
*
dev
,
char
*
ch_name
)
{
dma_cap_mask_t
mask
;
void
*
filter_param
;
...
...
@@ -33,7 +34,12 @@ static unsigned samsung_dmadev_request(enum dma_ch dma_ch,
*/
filter_param
=
(
dma_ch
==
DMACH_DT_PROP
)
?
(
void
*
)
param
->
dt_dmach_prop
:
(
void
*
)
dma_ch
;
return
(
unsigned
)
dma_request_channel
(
mask
,
pl330_filter
,
filter_param
);
if
(
dev
->
of_node
)
return
(
unsigned
)
dma_request_slave_channel
(
dev
,
ch_name
);
else
return
(
unsigned
)
dma_request_channel
(
mask
,
pl330_filter
,
filter_param
);
}
static
int
samsung_dmadev_release
(
unsigned
ch
,
void
*
param
)
...
...
arch/arm/plat-samsung/include/plat/dma-ops.h
浏览文件 @
2944c2f5
...
...
@@ -39,7 +39,8 @@ struct samsung_dma_config {
};
struct
samsung_dma_ops
{
unsigned
(
*
request
)(
enum
dma_ch
ch
,
struct
samsung_dma_req
*
param
);
unsigned
(
*
request
)(
enum
dma_ch
ch
,
struct
samsung_dma_req
*
param
,
struct
device
*
dev
,
char
*
ch_name
);
int
(
*
release
)(
unsigned
ch
,
void
*
param
);
int
(
*
config
)(
unsigned
ch
,
struct
samsung_dma_config
*
param
);
int
(
*
prepare
)(
unsigned
ch
,
struct
samsung_dma_prep
*
param
);
...
...
arch/arm/plat-samsung/s3c-dma-ops.c
浏览文件 @
2944c2f5
...
...
@@ -36,7 +36,8 @@ static void s3c_dma_cb(struct s3c2410_dma_chan *channel, void *param,
}
static
unsigned
s3c_dma_request
(
enum
dma_ch
dma_ch
,
struct
samsung_dma_req
*
param
)
struct
samsung_dma_req
*
param
,
struct
device
*
dev
,
char
*
ch_name
)
{
struct
cb_data
*
data
;
...
...
drivers/spi/spi-s3c64xx.c
浏览文件 @
2944c2f5
...
...
@@ -134,7 +134,6 @@ struct s3c64xx_spi_dma_data {
unsigned
ch
;
enum
dma_transfer_direction
direction
;
enum
dma_ch
dmach
;
struct
property
*
dma_prop
;
};
/**
...
...
@@ -319,16 +318,15 @@ static void prepare_dma(struct s3c64xx_spi_dma_data *dma,
static
int
acquire_dma
(
struct
s3c64xx_spi_driver_data
*
sdd
)
{
struct
samsung_dma_req
req
;
struct
device
*
dev
=
&
sdd
->
pdev
->
dev
;
sdd
->
ops
=
samsung_dma_get_ops
();
req
.
cap
=
DMA_SLAVE
;
req
.
client
=
&
s3c64xx_spi_dma_client
;
req
.
dt_dmach_prop
=
sdd
->
rx_dma
.
dma_prop
;
sdd
->
rx_dma
.
ch
=
sdd
->
ops
->
request
(
sdd
->
rx_dma
.
dmach
,
&
req
);
req
.
dt_dmach_prop
=
sdd
->
tx_dma
.
dma_prop
;
sdd
->
tx_dma
.
ch
=
sdd
->
ops
->
request
(
sdd
->
tx_dma
.
dmach
,
&
req
);
sdd
->
rx_dma
.
ch
=
sdd
->
ops
->
request
(
sdd
->
rx_dma
.
dmach
,
&
req
,
dev
,
"rx"
);
sdd
->
tx_dma
.
ch
=
sdd
->
ops
->
request
(
sdd
->
tx_dma
.
dmach
,
&
req
,
dev
,
"tx"
);
return
1
;
}
...
...
@@ -1054,49 +1052,6 @@ static void s3c64xx_spi_hwinit(struct s3c64xx_spi_driver_data *sdd, int channel)
flush_fifo
(
sdd
);
}
static
int
s3c64xx_spi_get_dmares
(
struct
s3c64xx_spi_driver_data
*
sdd
,
bool
tx
)
{
struct
platform_device
*
pdev
=
sdd
->
pdev
;
struct
s3c64xx_spi_dma_data
*
dma_data
;
struct
property
*
prop
;
struct
resource
*
res
;
char
prop_name
[
15
],
*
chan_str
;
if
(
tx
)
{
dma_data
=
&
sdd
->
tx_dma
;
dma_data
->
direction
=
DMA_MEM_TO_DEV
;
chan_str
=
"tx"
;
}
else
{
dma_data
=
&
sdd
->
rx_dma
;
dma_data
->
direction
=
DMA_DEV_TO_MEM
;
chan_str
=
"rx"
;
}
if
(
!
sdd
->
pdev
->
dev
.
of_node
)
{
res
=
platform_get_resource
(
pdev
,
IORESOURCE_DMA
,
tx
?
0
:
1
);
if
(
!
res
)
{
dev_err
(
&
pdev
->
dev
,
"Unable to get SPI-%s dma "
"resource
\n
"
,
chan_str
);
return
-
ENXIO
;
}
dma_data
->
dmach
=
res
->
start
;
return
0
;
}
sprintf
(
prop_name
,
"%s-dma-channel"
,
chan_str
);
prop
=
of_find_property
(
pdev
->
dev
.
of_node
,
prop_name
,
NULL
);
if
(
!
prop
)
{
dev_err
(
&
pdev
->
dev
,
"%s dma channel property not specified
\n
"
,
chan_str
);
return
-
ENXIO
;
}
dma_data
->
dmach
=
DMACH_DT_PROP
;
dma_data
->
dma_prop
=
prop
;
return
0
;
}
#ifdef CONFIG_OF
static
int
s3c64xx_spi_parse_dt_gpio
(
struct
s3c64xx_spi_driver_data
*
sdd
)
{
...
...
@@ -1198,6 +1153,7 @@ static inline struct s3c64xx_spi_port_config *s3c64xx_spi_get_port_config(
static
int
__init
s3c64xx_spi_probe
(
struct
platform_device
*
pdev
)
{
struct
resource
*
mem_res
;
struct
resource
*
res
;
struct
s3c64xx_spi_driver_data
*
sdd
;
struct
s3c64xx_spi_info
*
sci
=
pdev
->
dev
.
platform_data
;
struct
spi_master
*
master
;
...
...
@@ -1256,13 +1212,26 @@ static int __init s3c64xx_spi_probe(struct platform_device *pdev)
sdd
->
cur_bpw
=
8
;
ret
=
s3c64xx_spi_get_dmares
(
sdd
,
true
);
if
(
ret
)
goto
err0
;
if
(
!
sdd
->
pdev
->
dev
.
of_node
)
{
res
=
platform_get_resource
(
pdev
,
IORESOURCE_DMA
,
0
);
if
(
!
res
)
{
dev_err
(
&
pdev
->
dev
,
"Unable to get SPI tx dma "
"resource
\n
"
);
return
-
ENXIO
;
}
sdd
->
tx_dma
.
dmach
=
res
->
start
;
res
=
platform_get_resource
(
pdev
,
IORESOURCE_DMA
,
1
);
if
(
!
res
)
{
dev_err
(
&
pdev
->
dev
,
"Unable to get SPI rx dma "
"resource
\n
"
);
return
-
ENXIO
;
}
sdd
->
rx_dma
.
dmach
=
res
->
start
;
}
ret
=
s3c64xx_spi_get_dmares
(
sdd
,
false
);
if
(
ret
)
goto
err0
;
sdd
->
tx_dma
.
direction
=
DMA_MEM_TO_DEV
;
sdd
->
rx_dma
.
direction
=
DMA_DEV_TO_MEM
;
master
->
dev
.
of_node
=
pdev
->
dev
.
of_node
;
master
->
bus_num
=
sdd
->
port_id
;
...
...
sound/soc/samsung/Kconfig
浏览文件 @
2944c2f5
...
...
@@ -63,7 +63,7 @@ config SND_SOC_SAMSUNG_SMDK_WM8580
config SND_SOC_SAMSUNG_SMDK_WM8994
tristate "SoC I2S Audio support for WM8994 on SMDK"
depends on SND_SOC_SAMSUNG
&& (MACH_SMDKV310 || MACH_SMDKC210 || MACH_SMDK4212)
depends on SND_SOC_SAMSUNG
depends on I2C=y && GENERIC_HARDIRQS
select MFD_WM8994
select SND_SOC_WM8994
...
...
@@ -162,7 +162,7 @@ config SND_SOC_GONI_AQUILA_WM8994
config SND_SOC_SAMSUNG_SMDK_SPDIF
tristate "SoC S/PDIF Audio support for SMDK"
depends on SND_SOC_SAMSUNG
&& (MACH_SMDKC100 || MACH_SMDKC110 || MACH_SMDKV210 || MACH_SMDKV310 || MACH_SMDK4212)
depends on SND_SOC_SAMSUNG
select SND_SAMSUNG_SPDIF
help
Say Y if you want to add support for SoC S/PDIF audio on the SMDK.
...
...
@@ -177,7 +177,7 @@ config SND_SOC_SMDK_WM8580_PCM
config SND_SOC_SMDK_WM8994_PCM
tristate "SoC PCM Audio support for WM8994 on SMDK"
depends on SND_SOC_SAMSUNG
&& (MACH_SMDKC210 || MACH_SMDKV310 || MACH_SMDK4212)
depends on SND_SOC_SAMSUNG
depends on I2C=y && GENERIC_HARDIRQS
select MFD_WM8994
select SND_SOC_WM8994
...
...
sound/soc/samsung/dma.c
浏览文件 @
2944c2f5
...
...
@@ -174,7 +174,8 @@ static int dma_hw_params(struct snd_pcm_substream *substream,
config
.
width
=
prtd
->
params
->
dma_size
;
config
.
fifo
=
prtd
->
params
->
dma_addr
;
prtd
->
params
->
ch
=
prtd
->
params
->
ops
->
request
(
prtd
->
params
->
channel
,
&
req
);
prtd
->
params
->
channel
,
&
req
,
rtd
->
cpu_dai
->
dev
,
prtd
->
params
->
ch_name
);
prtd
->
params
->
ops
->
config
(
prtd
->
params
->
ch
,
&
config
);
}
...
...
sound/soc/samsung/dma.h
浏览文件 @
2944c2f5
...
...
@@ -19,6 +19,7 @@ struct s3c_dma_params {
int
dma_size
;
/* Size of the DMA transfer */
unsigned
ch
;
struct
samsung_dma_ops
*
ops
;
char
*
ch_name
;
};
int
asoc_dma_platform_register
(
struct
device
*
dev
);
...
...
sound/soc/samsung/i2s.c
浏览文件 @
2944c2f5
...
...
@@ -15,11 +15,15 @@
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/pm_runtime.h>
#include <sound/soc.h>
#include <sound/pcm_params.h>
#include <mach/dma.h>
#include <linux/platform_data/asoc-s3c.h>
#include "dma.h"
...
...
@@ -29,6 +33,15 @@
#define msecs_to_loops(t) (loops_per_jiffy / 1000 * HZ * t)
enum
samsung_dai_type
{
TYPE_PRI
,
TYPE_SEC
,
};
struct
samsung_i2s_dai_data
{
int
dai_type
;
};
struct
i2s_dai
{
/* Platform device for this DAI */
struct
platform_device
*
pdev
;
...
...
@@ -66,6 +79,7 @@ struct i2s_dai {
u32
suspend_i2smod
;
u32
suspend_i2scon
;
u32
suspend_i2spsr
;
unsigned
long
gpios
[
7
];
/* i2s gpio line numbers */
};
/* Lock for cross i/f checks */
...
...
@@ -651,6 +665,9 @@ static int i2s_startup(struct snd_pcm_substream *substream,
/* Enforce set_sysclk in Master mode */
i2s
->
rclk_srcrate
=
0
;
if
(
!
any_active
(
i2s
)
&&
(
i2s
->
quirks
&
QUIRK_NEED_RSTCLR
))
writel
(
CON_RSTCLR
,
i2s
->
addr
+
I2SCON
);
spin_unlock_irqrestore
(
&
lock
,
flags
);
return
0
;
...
...
@@ -981,8 +998,7 @@ static struct i2s_dai *i2s_alloc_dai(struct platform_device *pdev, bool sec)
i2s
->
i2s_dai_drv
.
capture
.
formats
=
SAMSUNG_I2S_FMTS
;
}
else
{
/* Create a new platform_device for Secondary */
i2s
->
pdev
=
platform_device_register_resndata
(
NULL
,
pdev
->
name
,
pdev
->
id
+
SAMSUNG_I2S_SECOFF
,
NULL
,
0
,
NULL
,
0
);
"samsung-i2s-sec"
,
-
1
,
NULL
,
0
,
NULL
,
0
);
if
(
IS_ERR
(
i2s
->
pdev
))
return
NULL
;
}
...
...
@@ -993,18 +1009,103 @@ static struct i2s_dai *i2s_alloc_dai(struct platform_device *pdev, bool sec)
return
i2s
;
}
#ifdef CONFIG_OF
static
int
samsung_i2s_parse_dt_gpio
(
struct
i2s_dai
*
i2s
)
{
struct
device
*
dev
=
&
i2s
->
pdev
->
dev
;
int
index
,
gpio
,
ret
;
for
(
index
=
0
;
index
<
7
;
index
++
)
{
gpio
=
of_get_gpio
(
dev
->
of_node
,
index
);
if
(
!
gpio_is_valid
(
gpio
))
{
dev_err
(
dev
,
"invalid gpio[%d]: %d
\n
"
,
index
,
gpio
);
goto
free_gpio
;
}
ret
=
gpio_request
(
gpio
,
dev_name
(
dev
));
if
(
ret
)
{
dev_err
(
dev
,
"gpio [%d] request failed
\n
"
,
gpio
);
goto
free_gpio
;
}
i2s
->
gpios
[
index
]
=
gpio
;
}
return
0
;
free_gpio:
while
(
--
index
>=
0
)
gpio_free
(
i2s
->
gpios
[
index
]);
return
-
EINVAL
;
}
static
void
samsung_i2s_dt_gpio_free
(
struct
i2s_dai
*
i2s
)
{
unsigned
int
index
;
for
(
index
=
0
;
index
<
7
;
index
++
)
gpio_free
(
i2s
->
gpios
[
index
]);
}
#else
static
int
samsung_i2s_parse_dt_gpio
(
struct
i2s_dai
*
dai
)
{
return
-
EINVAL
;
}
static
void
samsung_i2s_dt_gpio_free
(
struct
i2s_dai
*
dai
)
{
}
#endif
static
const
struct
of_device_id
exynos_i2s_match
[];
static
inline
int
samsung_i2s_get_driver_data
(
struct
platform_device
*
pdev
)
{
#ifdef CONFIG_OF
struct
samsung_i2s_dai_data
*
data
;
if
(
pdev
->
dev
.
of_node
)
{
const
struct
of_device_id
*
match
;
match
=
of_match_node
(
exynos_i2s_match
,
pdev
->
dev
.
of_node
);
data
=
(
struct
samsung_i2s_dai_data
*
)
match
->
data
;
return
data
->
dai_type
;
}
else
#endif
return
platform_get_device_id
(
pdev
)
->
driver_data
;
}
#ifdef CONFIG_PM_RUNTIME
static
int
i2s_runtime_suspend
(
struct
device
*
dev
)
{
struct
i2s_dai
*
i2s
=
dev_get_drvdata
(
dev
);
clk_disable_unprepare
(
i2s
->
clk
);
return
0
;
}
static
int
i2s_runtime_resume
(
struct
device
*
dev
)
{
struct
i2s_dai
*
i2s
=
dev_get_drvdata
(
dev
);
clk_prepare_enable
(
i2s
->
clk
);
return
0
;
}
#endif
/* CONFIG_PM_RUNTIME */
static
int
samsung_i2s_probe
(
struct
platform_device
*
pdev
)
{
u32
dma_pl_chan
,
dma_cp_chan
,
dma_pl_sec_chan
;
struct
i2s_dai
*
pri_dai
,
*
sec_dai
=
NULL
;
struct
s3c_audio_pdata
*
i2s_pdata
;
struct
samsung_i2s
*
i2s_cfg
;
struct
s3c_audio_pdata
*
i2s_pdata
=
pdev
->
dev
.
platform_data
;
struct
samsung_i2s
*
i2s_cfg
=
NULL
;
struct
resource
*
res
;
u32
regs_base
,
quirks
;
u32
regs_base
,
quirks
=
0
,
idma_addr
=
0
;
struct
device_node
*
np
=
pdev
->
dev
.
of_node
;
enum
samsung_dai_type
samsung_dai_type
;
int
ret
=
0
;
/* Call during Seconday interface registration */
if
(
pdev
->
id
>=
SAMSUNG_I2S_SECOFF
)
{
samsung_dai_type
=
samsung_i2s_get_driver_data
(
pdev
);
if
(
samsung_dai_type
==
TYPE_SEC
)
{
sec_dai
=
dev_get_drvdata
(
&
pdev
->
dev
);
snd_soc_register_dai
(
&
sec_dai
->
pdev
->
dev
,
&
sec_dai
->
i2s_dai_drv
);
...
...
@@ -1012,31 +1113,60 @@ static int samsung_i2s_probe(struct platform_device *pdev)
return
0
;
}
i2s_pdata
=
pdev
->
dev
.
platform_data
;
if
(
i2s_pdata
==
NULL
)
{
dev_err
(
&
pdev
->
dev
,
"
Can't work without s3c_audio_pdata
\n
"
);
return
-
E
INVAL
;
pri_dai
=
i2s_alloc_dai
(
pdev
,
false
)
;
if
(
!
pri_dai
)
{
dev_err
(
&
pdev
->
dev
,
"
Unable to alloc I2S_pri
\n
"
);
return
-
E
NOMEM
;
}
res
=
platform_get_resource
(
pdev
,
IORESOURCE_DMA
,
0
);
if
(
!
res
)
{
dev_err
(
&
pdev
->
dev
,
"Unable to get I2S-TX dma resource
\n
"
);
return
-
ENXIO
;
}
dma_pl_chan
=
res
->
start
;
if
(
!
np
)
{
res
=
platform_get_resource
(
pdev
,
IORESOURCE_DMA
,
0
);
if
(
!
res
)
{
dev_err
(
&
pdev
->
dev
,
"Unable to get I2S-TX dma resource
\n
"
);
return
-
ENXIO
;
}
pri_dai
->
dma_playback
.
channel
=
res
->
start
;
res
=
platform_get_resource
(
pdev
,
IORESOURCE_DMA
,
1
);
if
(
!
res
)
{
dev_err
(
&
pdev
->
dev
,
"Unable to get I2S-RX dma resource
\n
"
);
return
-
ENXIO
;
}
dma_cp_chan
=
res
->
start
;
res
=
platform_get_resource
(
pdev
,
IORESOURCE_DMA
,
1
);
if
(
!
res
)
{
dev_err
(
&
pdev
->
dev
,
"Unable to get I2S-RX dma resource
\n
"
);
return
-
ENXIO
;
}
pri_dai
->
dma_capture
.
channel
=
res
->
start
;
res
=
platform_get_resource
(
pdev
,
IORESOURCE_DMA
,
2
);
if
(
res
)
dma_pl_sec_chan
=
res
->
start
;
else
dma_pl_sec_chan
=
0
;
if
(
i2s_pdata
==
NULL
)
{
dev_err
(
&
pdev
->
dev
,
"Can't work without s3c_audio_pdata
\n
"
);
return
-
EINVAL
;
}
if
(
&
i2s_pdata
->
type
)
i2s_cfg
=
&
i2s_pdata
->
type
.
i2s
;
if
(
i2s_cfg
)
{
quirks
=
i2s_cfg
->
quirks
;
idma_addr
=
i2s_cfg
->
idma_addr
;
}
}
else
{
if
(
of_find_property
(
np
,
"samsung,supports-6ch"
,
NULL
))
quirks
|=
QUIRK_PRI_6CHAN
;
if
(
of_find_property
(
np
,
"samsung,supports-secdai"
,
NULL
))
quirks
|=
QUIRK_SEC_DAI
;
if
(
of_find_property
(
np
,
"samsung,supports-rstclr"
,
NULL
))
quirks
|=
QUIRK_NEED_RSTCLR
;
if
(
of_property_read_u32
(
np
,
"samsung,idma-addr"
,
&
idma_addr
))
{
if
(
quirks
&
QUIRK_SEC_DAI
)
{
dev_err
(
&
pdev
->
dev
,
"idma address is not"
\
"specified"
);
return
-
EINVAL
;
}
}
}
res
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
0
);
if
(
!
res
)
{
...
...
@@ -1051,24 +1181,14 @@ static int samsung_i2s_probe(struct platform_device *pdev)
}
regs_base
=
res
->
start
;
i2s_cfg
=
&
i2s_pdata
->
type
.
i2s
;
quirks
=
i2s_cfg
->
quirks
;
pri_dai
=
i2s_alloc_dai
(
pdev
,
false
);
if
(
!
pri_dai
)
{
dev_err
(
&
pdev
->
dev
,
"Unable to alloc I2S_pri
\n
"
);
ret
=
-
ENOMEM
;
goto
err
;
}
pri_dai
->
dma_playback
.
dma_addr
=
regs_base
+
I2STXD
;
pri_dai
->
dma_capture
.
dma_addr
=
regs_base
+
I2SRXD
;
pri_dai
->
dma_playback
.
client
=
(
struct
s3c2410_dma_client
*
)
&
pri_dai
->
dma_playback
;
pri_dai
->
dma_playback
.
ch_name
=
"tx"
;
pri_dai
->
dma_capture
.
client
=
(
struct
s3c2410_dma_client
*
)
&
pri_dai
->
dma_capture
;
pri_dai
->
dma_playback
.
channel
=
dma_pl_chan
;
pri_dai
->
dma_capture
.
channel
=
dma_cp_chan
;
pri_dai
->
dma_capture
.
ch_name
=
"rx"
;
pri_dai
->
dma_playback
.
dma_size
=
4
;
pri_dai
->
dma_capture
.
dma_size
=
4
;
pri_dai
->
base
=
regs_base
;
...
...
@@ -1087,20 +1207,34 @@ static int samsung_i2s_probe(struct platform_device *pdev)
sec_dai
->
dma_playback
.
dma_addr
=
regs_base
+
I2STXDS
;
sec_dai
->
dma_playback
.
client
=
(
struct
s3c2410_dma_client
*
)
&
sec_dai
->
dma_playback
;
/* Use iDMA always if SysDMA not provided */
sec_dai
->
dma_playback
.
channel
=
dma_pl_sec_chan
?
:
-
1
;
sec_dai
->
dma_playback
.
ch_name
=
"tx-sec"
;
if
(
!
np
)
{
res
=
platform_get_resource
(
pdev
,
IORESOURCE_DMA
,
2
);
if
(
res
)
sec_dai
->
dma_playback
.
channel
=
res
->
start
;
}
sec_dai
->
dma_playback
.
dma_size
=
4
;
sec_dai
->
base
=
regs_base
;
sec_dai
->
quirks
=
quirks
;
sec_dai
->
idma_playback
.
dma_addr
=
i
2s_cfg
->
i
dma_addr
;
sec_dai
->
idma_playback
.
dma_addr
=
idma_addr
;
sec_dai
->
pri_dai
=
pri_dai
;
pri_dai
->
sec_dai
=
sec_dai
;
}
if
(
i2s_pdata
->
cfg_gpio
&&
i2s_pdata
->
cfg_gpio
(
pdev
))
{
dev_err
(
&
pdev
->
dev
,
"Unable to configure gpio
\n
"
);
ret
=
-
EINVAL
;
goto
err
;
if
(
np
)
{
if
(
samsung_i2s_parse_dt_gpio
(
pri_dai
))
{
dev_err
(
&
pdev
->
dev
,
"Unable to configure gpio
\n
"
);
ret
=
-
EINVAL
;
goto
err
;
}
}
else
{
if
(
i2s_pdata
->
cfg_gpio
&&
i2s_pdata
->
cfg_gpio
(
pdev
))
{
dev_err
(
&
pdev
->
dev
,
"Unable to configure gpio
\n
"
);
ret
=
-
EINVAL
;
goto
err
;
}
}
snd_soc_register_dai
(
&
pri_dai
->
pdev
->
dev
,
&
pri_dai
->
i2s_dai_drv
);
...
...
@@ -1120,10 +1254,14 @@ static int samsung_i2s_remove(struct platform_device *pdev)
{
struct
i2s_dai
*
i2s
,
*
other
;
struct
resource
*
res
;
struct
s3c_audio_pdata
*
i2s_pdata
=
pdev
->
dev
.
platform_data
;
i2s
=
dev_get_drvdata
(
&
pdev
->
dev
);
other
=
i2s
->
pri_dai
?
:
i2s
->
sec_dai
;
if
(
!
i2s_pdata
->
cfg_gpio
&&
pdev
->
dev
.
of_node
)
samsung_i2s_dt_gpio_free
(
i2s
->
pri_dai
);
if
(
other
)
{
other
->
pri_dai
=
NULL
;
other
->
sec_dai
=
NULL
;
...
...
@@ -1143,12 +1281,47 @@ static int samsung_i2s_remove(struct platform_device *pdev)
return
0
;
}
static
struct
platform_device_id
samsung_i2s_driver_ids
[]
=
{
{
.
name
=
"samsung-i2s"
,
.
driver_data
=
TYPE_PRI
,
},
{
.
name
=
"samsung-i2s-sec"
,
.
driver_data
=
TYPE_SEC
,
},
{},
};
MODULE_DEVICE_TABLE
(
platform
,
samsung
-
i2s
-
driver
-
ids
);
#ifdef CONFIG_OF
static
struct
samsung_i2s_dai_data
samsung_i2s_dai_data_array
[]
=
{
[
TYPE_PRI
]
=
{
TYPE_PRI
},
[
TYPE_SEC
]
=
{
TYPE_SEC
},
};
static
const
struct
of_device_id
exynos_i2s_match
[]
=
{
{
.
compatible
=
"samsung,i2s-v5"
,
.
data
=
&
samsung_i2s_dai_data_array
[
TYPE_PRI
],
},
{},
};
MODULE_DEVICE_TABLE
(
of
,
exynos_i2s_match
);
#endif
static
const
struct
dev_pm_ops
samsung_i2s_pm
=
{
SET_RUNTIME_PM_OPS
(
i2s_runtime_suspend
,
i2s_runtime_resume
,
NULL
)
};
static
struct
platform_driver
samsung_i2s_driver
=
{
.
probe
=
samsung_i2s_probe
,
.
remove
=
samsung_i2s_remove
,
.
id_table
=
samsung_i2s_driver_ids
,
.
driver
=
{
.
name
=
"samsung-i2s"
,
.
owner
=
THIS_MODULE
,
.
of_match_table
=
of_match_ptr
(
exynos_i2s_match
),
.
pm
=
&
samsung_i2s_pm
,
},
};
...
...
sound/soc/samsung/i2s.h
浏览文件 @
2944c2f5
...
...
@@ -13,13 +13,6 @@
#ifndef __SND_SOC_SAMSUNG_I2S_H
#define __SND_SOC_SAMSUNG_I2S_H
/*
* Maximum number of I2S blocks that any SoC can have.
* The secondary interface of a CPU dai(if there exists any),
* is indexed at [cpu-dai's ID + SAMSUNG_I2S_SECOFF]
*/
#define SAMSUNG_I2S_SECOFF 4
#define SAMSUNG_I2S_DIV_BCLK 1
#define SAMSUNG_I2S_RCLKSRC_0 0
...
...
sound/soc/samsung/smdk_wm8580.c
浏览文件 @
2944c2f5
...
...
@@ -193,9 +193,9 @@ static struct snd_soc_dai_link smdk_dai[] = {
[
SEC_PLAYBACK
]
=
{
/* Sec_Fifo Playback i/f */
.
name
=
"Sec_FIFO TX"
,
.
stream_name
=
"Playback"
,
.
cpu_dai_name
=
"samsung-i2s
.x
"
,
.
cpu_dai_name
=
"samsung-i2s
-sec
"
,
.
codec_dai_name
=
"wm8580-hifi-playback"
,
.
platform_name
=
"samsung-i2s
.x
"
,
.
platform_name
=
"samsung-i2s
-sec
"
,
.
codec_name
=
"wm8580.0-001b"
,
.
ops
=
&
smdk_ops
,
},
...
...
@@ -223,9 +223,6 @@ static int __init smdk_audio_init(void)
if
(
machine_is_smdkc100
()
||
machine_is_smdkv210
()
||
machine_is_smdkc110
())
{
smdk
.
num_links
=
3
;
/* Secondary is at offset SAMSUNG_I2S_SECOFF from Primary */
str
=
(
char
*
)
smdk_dai
[
SEC_PLAYBACK
].
cpu_dai_name
;
str
[
strlen
(
str
)
-
1
]
=
'0'
+
SAMSUNG_I2S_SECOFF
;
}
else
if
(
machine_is_smdk6410
())
{
str
=
(
char
*
)
smdk_dai
[
PRI_PLAYBACK
].
cpu_dai_name
;
str
[
strlen
(
str
)
-
1
]
=
'2'
;
...
...
sound/soc/samsung/smdk_wm8994.c
浏览文件 @
2944c2f5
...
...
@@ -10,6 +10,7 @@
#include "../codecs/wm8994.h"
#include <sound/pcm_params.h>
#include <linux/module.h>
#include <linux/of.h>
/*
* Default CFG switch settings to use this driver:
...
...
@@ -134,9 +135,9 @@ static struct snd_soc_dai_link smdk_dai[] = {
},
{
/* Sec_Fifo Playback i/f */
.
name
=
"Sec_FIFO TX"
,
.
stream_name
=
"Sec_Dai"
,
.
cpu_dai_name
=
"samsung-i2s
.4
"
,
.
cpu_dai_name
=
"samsung-i2s
-sec
"
,
.
codec_dai_name
=
"wm8994-aif1"
,
.
platform_name
=
"samsung-i2s
.4
"
,
.
platform_name
=
"samsung-i2s
-sec
"
,
.
codec_name
=
"wm8994-codec"
,
.
ops
=
&
smdk_ops
,
},
...
...
@@ -153,9 +154,25 @@ static struct snd_soc_card smdk = {
static
int
smdk_audio_probe
(
struct
platform_device
*
pdev
)
{
int
ret
;
struct
device_node
*
np
=
pdev
->
dev
.
of_node
;
struct
snd_soc_card
*
card
=
&
smdk
;
card
->
dev
=
&
pdev
->
dev
;
if
(
np
)
{
smdk_dai
[
0
].
cpu_dai_name
=
NULL
;
smdk_dai
[
0
].
cpu_of_node
=
of_parse_phandle
(
np
,
"samsung,i2s-controller"
,
0
);
if
(
!
smdk_dai
[
0
].
cpu_of_node
)
{
dev_err
(
&
pdev
->
dev
,
"Property 'samsung,i2s-controller' missing or invalid
\n
"
);
ret
=
-
EINVAL
;
}
smdk_dai
[
0
].
platform_name
=
NULL
;
smdk_dai
[
0
].
platform_of_node
=
smdk_dai
[
0
].
cpu_of_node
;
}
ret
=
snd_soc_register_card
(
card
);
if
(
ret
)
...
...
@@ -173,10 +190,19 @@ static int smdk_audio_remove(struct platform_device *pdev)
return
0
;
}
#ifdef CONFIG_OF
static
const
struct
of_device_id
samsung_wm8994_of_match
[]
=
{
{
.
compatible
=
"samsung,smdk-wm8994"
,
},
{},
};
MODULE_DEVICE_TABLE
(
of
,
samsung_wm8994_of_match
);
#endif
/* CONFIG_OF */
static
struct
platform_driver
smdk_audio_driver
=
{
.
driver
=
{
.
name
=
"smdk-audio"
,
.
owner
=
THIS_MODULE
,
.
of_match_table
=
of_match_ptr
(
samsung_wm8994_of_match
),
},
.
probe
=
smdk_audio_probe
,
.
remove
=
smdk_audio_remove
,
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录