Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
cloud-kernel
提交
2fd53734
cloud-kernel
项目概览
openanolis
/
cloud-kernel
1 年多 前同步成功
通知
161
Star
36
Fork
7
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
10
列表
看板
标记
里程碑
合并请求
2
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
cloud-kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
10
Issue
10
列表
看板
标记
里程碑
合并请求
2
合并请求
2
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
2fd53734
编写于
8月 04, 2014
作者:
M
Mark Brown
浏览文件
操作
浏览文件
下载
差异文件
Merge remote-tracking branch 'asoc/topic/rcar' into asoc-next
上级
0e76ee41
cd2b6574
变更
14
显示空白变更内容
内联
并排
Showing
14 changed file
with
668 addition
and
621 deletion
+668
-621
Documentation/devicetree/bindings/sound/renesas,rsnd.txt
Documentation/devicetree/bindings/sound/renesas,rsnd.txt
+9
-0
arch/arm/mach-shmobile/board-armadillo800eva.c
arch/arm/mach-shmobile/board-armadillo800eva.c
+4
-0
arch/arm/mach-shmobile/board-kzm9g.c
arch/arm/mach-shmobile/board-kzm9g.c
+2
-0
arch/arm/mach-shmobile/board-mackerel.c
arch/arm/mach-shmobile/board-mackerel.c
+4
-0
arch/sh/boards/mach-ecovec24/setup.c
arch/sh/boards/mach-ecovec24/setup.c
+2
-0
include/sound/rcar_snd.h
include/sound/rcar_snd.h
+1
-0
sound/soc/sh/Kconfig
sound/soc/sh/Kconfig
+1
-1
sound/soc/sh/fsi.c
sound/soc/sh/fsi.c
+52
-137
sound/soc/sh/rcar/core.c
sound/soc/sh/rcar/core.c
+118
-125
sound/soc/sh/rcar/dvc.c
sound/soc/sh/rcar/dvc.c
+101
-34
sound/soc/sh/rcar/gen.c
sound/soc/sh/rcar/gen.c
+252
-301
sound/soc/sh/rcar/rsnd.h
sound/soc/sh/rcar/rsnd.h
+15
-11
sound/soc/sh/rcar/src.c
sound/soc/sh/rcar/src.c
+76
-10
sound/soc/sh/rcar/ssi.c
sound/soc/sh/rcar/ssi.c
+31
-2
未找到文件。
Documentation/devicetree/bindings/sound/renesas,rsnd.txt
浏览文件 @
2fd53734
...
@@ -13,6 +13,9 @@ Required properties:
...
@@ -13,6 +13,9 @@ Required properties:
- rcar_sound,src : Should contain SRC feature.
- rcar_sound,src : Should contain SRC feature.
The number of SRC subnode should be same as HW.
The number of SRC subnode should be same as HW.
see below for detail.
see below for detail.
- rcar_sound,dvc : Should contain DVC feature.
The number of DVC subnode should be same as HW.
see below for detail.
- rcar_sound,dai : DAI contents.
- rcar_sound,dai : DAI contents.
The number of DAI subnode should be same as HW.
The number of DAI subnode should be same as HW.
see below for detail.
see below for detail.
...
@@ -21,6 +24,7 @@ SSI subnode properties:
...
@@ -21,6 +24,7 @@ SSI subnode properties:
- interrupts : Should contain SSI interrupt for PIO transfer
- interrupts : Should contain SSI interrupt for PIO transfer
- shared-pin : if shared clock pin
- shared-pin : if shared clock pin
- pio-transfer : use PIO transfer mode
- pio-transfer : use PIO transfer mode
- no-busif : BUSIF is not ussed when [mem -> SSI] via DMA case
SRC subnode properties:
SRC subnode properties:
no properties at this point
no properties at this point
...
@@ -39,6 +43,11 @@ rcar_sound: rcar_sound@0xffd90000 {
...
@@ -39,6 +43,11 @@ rcar_sound: rcar_sound@0xffd90000 {
<0 0xec540000 0 0x1000>, /* SSIU */
<0 0xec540000 0 0x1000>, /* SSIU */
<0 0xec541000 0 0x1280>; /* SSI */
<0 0xec541000 0 0x1280>; /* SSI */
rcar_sound,dvc {
dvc0: dvc@0 { };
dvc1: dvc@1 { };
};
rcar_sound,src {
rcar_sound,src {
src0: src@0 { };
src0: src@0 { };
src1: src@1 { };
src1: src@1 { };
...
...
arch/arm/mach-shmobile/board-armadillo800eva.c
浏览文件 @
2fd53734
...
@@ -998,6 +998,8 @@ static struct platform_device fsi_wm8978_device = {
...
@@ -998,6 +998,8 @@ static struct platform_device fsi_wm8978_device = {
.
id
=
0
,
.
id
=
0
,
.
dev
=
{
.
dev
=
{
.
platform_data
=
&
fsi_wm8978_info
,
.
platform_data
=
&
fsi_wm8978_info
,
.
coherent_dma_mask
=
DMA_BIT_MASK
(
32
),
.
dma_mask
=
&
fsi_wm8978_device
.
dev
.
coherent_dma_mask
,
},
},
};
};
...
@@ -1021,6 +1023,8 @@ static struct platform_device fsi_hdmi_device = {
...
@@ -1021,6 +1023,8 @@ static struct platform_device fsi_hdmi_device = {
.
id
=
1
,
.
id
=
1
,
.
dev
=
{
.
dev
=
{
.
platform_data
=
&
fsi2_hdmi_info
,
.
platform_data
=
&
fsi2_hdmi_info
,
.
coherent_dma_mask
=
DMA_BIT_MASK
(
32
),
.
dma_mask
=
&
fsi_hdmi_device
.
dev
.
coherent_dma_mask
,
},
},
};
};
...
...
arch/arm/mach-shmobile/board-kzm9g.c
浏览文件 @
2fd53734
...
@@ -603,6 +603,8 @@ static struct platform_device fsi_ak4648_device = {
...
@@ -603,6 +603,8 @@ static struct platform_device fsi_ak4648_device = {
.
name
=
"asoc-simple-card"
,
.
name
=
"asoc-simple-card"
,
.
dev
=
{
.
dev
=
{
.
platform_data
=
&
fsi2_ak4648_info
,
.
platform_data
=
&
fsi2_ak4648_info
,
.
coherent_dma_mask
=
DMA_BIT_MASK
(
32
),
.
dma_mask
=
&
fsi_ak4648_device
.
dev
.
coherent_dma_mask
,
},
},
};
};
...
...
arch/arm/mach-shmobile/board-mackerel.c
浏览文件 @
2fd53734
...
@@ -523,6 +523,8 @@ static struct platform_device fsi_hdmi_device = {
...
@@ -523,6 +523,8 @@ static struct platform_device fsi_hdmi_device = {
.
id
=
1
,
.
id
=
1
,
.
dev
=
{
.
dev
=
{
.
platform_data
=
&
fsi2_hdmi_info
,
.
platform_data
=
&
fsi2_hdmi_info
,
.
coherent_dma_mask
=
DMA_BIT_MASK
(
32
),
.
dma_mask
=
&
fsi_hdmi_device
.
dev
.
coherent_dma_mask
,
},
},
};
};
...
@@ -919,6 +921,8 @@ static struct platform_device fsi_ak4643_device = {
...
@@ -919,6 +921,8 @@ static struct platform_device fsi_ak4643_device = {
.
name
=
"asoc-simple-card"
,
.
name
=
"asoc-simple-card"
,
.
dev
=
{
.
dev
=
{
.
platform_data
=
&
fsi2_ak4643_info
,
.
platform_data
=
&
fsi2_ak4643_info
,
.
coherent_dma_mask
=
DMA_BIT_MASK
(
32
),
.
dma_mask
=
&
fsi_ak4643_device
.
dev
.
coherent_dma_mask
,
},
},
};
};
...
...
arch/sh/boards/mach-ecovec24/setup.c
浏览文件 @
2fd53734
...
@@ -874,6 +874,8 @@ static struct platform_device fsi_da7210_device = {
...
@@ -874,6 +874,8 @@ static struct platform_device fsi_da7210_device = {
.
name
=
"asoc-simple-card"
,
.
name
=
"asoc-simple-card"
,
.
dev
=
{
.
dev
=
{
.
platform_data
=
&
fsi_da7210_info
,
.
platform_data
=
&
fsi_da7210_info
,
.
coherent_dma_mask
=
DMA_BIT_MASK
(
32
),
.
dma_mask
=
&
fsi_da7210_device
.
dev
.
coherent_dma_mask
,
},
},
};
};
...
...
include/sound/rcar_snd.h
浏览文件 @
2fd53734
...
@@ -34,6 +34,7 @@
...
@@ -34,6 +34,7 @@
* B : SSI direction
* B : SSI direction
*/
*/
#define RSND_SSI_CLK_PIN_SHARE (1 << 31)
#define RSND_SSI_CLK_PIN_SHARE (1 << 31)
#define RSND_SSI_NO_BUSIF (1 << 30)
/* SSI+DMA without BUSIF */
#define RSND_SSI(_dma_id, _pio_irq, _flags) \
#define RSND_SSI(_dma_id, _pio_irq, _flags) \
{ .dma_id = _dma_id, .pio_irq = _pio_irq, .flags = _flags }
{ .dma_id = _dma_id, .pio_irq = _pio_irq, .flags = _flags }
...
...
sound/soc/sh/Kconfig
浏览文件 @
2fd53734
...
@@ -37,7 +37,7 @@ config SND_SOC_SH4_SIU
...
@@ -37,7 +37,7 @@ config SND_SOC_SH4_SIU
config SND_SOC_RCAR
config SND_SOC_RCAR
tristate "R-Car series SRU/SCU/SSIU/SSI support"
tristate "R-Car series SRU/SCU/SSIU/SSI support"
select SND_SIMPLE_CARD
select SND_SIMPLE_CARD
select REGMAP
select REGMAP
_MMIO
help
help
This option enables R-Car SUR/SCU/SSIU/SSI sound support
This option enables R-Car SUR/SCU/SSIU/SSI sound support
...
...
sound/soc/sh/fsi.c
浏览文件 @
2fd53734
...
@@ -232,11 +232,7 @@ struct fsi_stream {
...
@@ -232,11 +232,7 @@ struct fsi_stream {
* these are for DMAEngine
* these are for DMAEngine
*/
*/
struct
dma_chan
*
chan
;
struct
dma_chan
*
chan
;
struct
work_struct
work
;
dma_addr_t
dma
;
int
dma_id
;
int
dma_id
;
int
loop_cnt
;
int
additional_pos
;
};
};
struct
fsi_clk
{
struct
fsi_clk
{
...
@@ -1042,6 +1038,26 @@ static int fsi_clk_set_rate_cpg(struct device *dev,
...
@@ -1042,6 +1038,26 @@ static int fsi_clk_set_rate_cpg(struct device *dev,
return
ret
;
return
ret
;
}
}
static
void
fsi_pointer_update
(
struct
fsi_stream
*
io
,
int
size
)
{
io
->
buff_sample_pos
+=
size
;
if
(
io
->
buff_sample_pos
>=
io
->
period_samples
*
(
io
->
period_pos
+
1
))
{
struct
snd_pcm_substream
*
substream
=
io
->
substream
;
struct
snd_pcm_runtime
*
runtime
=
substream
->
runtime
;
io
->
period_pos
++
;
if
(
io
->
period_pos
>=
runtime
->
periods
)
{
io
->
buff_sample_pos
=
0
;
io
->
period_pos
=
0
;
}
snd_pcm_period_elapsed
(
substream
);
}
}
/*
/*
* pio data transfer handler
* pio data transfer handler
*/
*/
...
@@ -1108,31 +1124,11 @@ static int fsi_pio_transfer(struct fsi_priv *fsi, struct fsi_stream *io,
...
@@ -1108,31 +1124,11 @@ static int fsi_pio_transfer(struct fsi_priv *fsi, struct fsi_stream *io,
void
(
*
run32
)(
struct
fsi_priv
*
fsi
,
u8
*
buf
,
int
samples
),
void
(
*
run32
)(
struct
fsi_priv
*
fsi
,
u8
*
buf
,
int
samples
),
int
samples
)
int
samples
)
{
{
struct
snd_pcm_runtime
*
runtime
;
struct
snd_pcm_substream
*
substream
;
u8
*
buf
;
u8
*
buf
;
int
over_period
;
if
(
!
fsi_stream_is_working
(
fsi
,
io
))
if
(
!
fsi_stream_is_working
(
fsi
,
io
))
return
-
EINVAL
;
return
-
EINVAL
;
over_period
=
0
;
substream
=
io
->
substream
;
runtime
=
substream
->
runtime
;
/* FSI FIFO has limit.
* So, this driver can not send periods data at a time
*/
if
(
io
->
buff_sample_pos
>=
io
->
period_samples
*
(
io
->
period_pos
+
1
))
{
over_period
=
1
;
io
->
period_pos
=
(
io
->
period_pos
+
1
)
%
runtime
->
periods
;
if
(
0
==
io
->
period_pos
)
io
->
buff_sample_pos
=
0
;
}
buf
=
fsi_pio_get_area
(
fsi
,
io
);
buf
=
fsi_pio_get_area
(
fsi
,
io
);
switch
(
io
->
sample_width
)
{
switch
(
io
->
sample_width
)
{
...
@@ -1146,11 +1142,7 @@ static int fsi_pio_transfer(struct fsi_priv *fsi, struct fsi_stream *io,
...
@@ -1146,11 +1142,7 @@ static int fsi_pio_transfer(struct fsi_priv *fsi, struct fsi_stream *io,
return
-
EINVAL
;
return
-
EINVAL
;
}
}
/* update buff_sample_pos */
fsi_pointer_update
(
io
,
samples
);
io
->
buff_sample_pos
+=
samples
;
if
(
over_period
)
snd_pcm_period_elapsed
(
substream
);
return
0
;
return
0
;
}
}
...
@@ -1279,11 +1271,6 @@ static irqreturn_t fsi_interrupt(int irq, void *data)
...
@@ -1279,11 +1271,6 @@ static irqreturn_t fsi_interrupt(int irq, void *data)
*/
*/
static
int
fsi_dma_init
(
struct
fsi_priv
*
fsi
,
struct
fsi_stream
*
io
)
static
int
fsi_dma_init
(
struct
fsi_priv
*
fsi
,
struct
fsi_stream
*
io
)
{
{
struct
snd_pcm_runtime
*
runtime
=
io
->
substream
->
runtime
;
struct
snd_soc_dai
*
dai
=
fsi_get_dai
(
io
->
substream
);
enum
dma_data_direction
dir
=
fsi_stream_is_play
(
fsi
,
io
)
?
DMA_TO_DEVICE
:
DMA_FROM_DEVICE
;
/*
/*
* 24bit data : 24bit bus / package in back
* 24bit data : 24bit bus / package in back
* 16bit data : 16bit bus / stream mode
* 16bit data : 16bit bus / stream mode
...
@@ -1291,91 +1278,37 @@ static int fsi_dma_init(struct fsi_priv *fsi, struct fsi_stream *io)
...
@@ -1291,91 +1278,37 @@ static int fsi_dma_init(struct fsi_priv *fsi, struct fsi_stream *io)
io
->
bus_option
=
BUSOP_SET
(
24
,
PACKAGE_24BITBUS_BACK
)
|
io
->
bus_option
=
BUSOP_SET
(
24
,
PACKAGE_24BITBUS_BACK
)
|
BUSOP_SET
(
16
,
PACKAGE_16BITBUS_STREAM
);
BUSOP_SET
(
16
,
PACKAGE_16BITBUS_STREAM
);
io
->
loop_cnt
=
2
;
/* push 1st, 2nd period first, then 3rd, 4th... */
io
->
additional_pos
=
0
;
io
->
dma
=
dma_map_single
(
dai
->
dev
,
runtime
->
dma_area
,
snd_pcm_lib_buffer_bytes
(
io
->
substream
),
dir
);
return
0
;
}
static
int
fsi_dma_quit
(
struct
fsi_priv
*
fsi
,
struct
fsi_stream
*
io
)
{
struct
snd_soc_dai
*
dai
=
fsi_get_dai
(
io
->
substream
);
enum
dma_data_direction
dir
=
fsi_stream_is_play
(
fsi
,
io
)
?
DMA_TO_DEVICE
:
DMA_FROM_DEVICE
;
dma_unmap_single
(
dai
->
dev
,
io
->
dma
,
snd_pcm_lib_buffer_bytes
(
io
->
substream
),
dir
);
return
0
;
return
0
;
}
}
static
dma_addr_t
fsi_dma_get_area
(
struct
fsi_stream
*
io
,
int
additional
)
{
struct
snd_pcm_runtime
*
runtime
=
io
->
substream
->
runtime
;
int
period
=
io
->
period_pos
+
additional
;
if
(
period
>=
runtime
->
periods
)
period
=
0
;
return
io
->
dma
+
samples_to_bytes
(
runtime
,
period
*
io
->
period_samples
);
}
static
void
fsi_dma_complete
(
void
*
data
)
static
void
fsi_dma_complete
(
void
*
data
)
{
{
struct
fsi_stream
*
io
=
(
struct
fsi_stream
*
)
data
;
struct
fsi_stream
*
io
=
(
struct
fsi_stream
*
)
data
;
struct
fsi_priv
*
fsi
=
fsi_stream_to_priv
(
io
);
struct
fsi_priv
*
fsi
=
fsi_stream_to_priv
(
io
);
struct
snd_pcm_runtime
*
runtime
=
io
->
substream
->
runtime
;
struct
snd_soc_dai
*
dai
=
fsi_get_dai
(
io
->
substream
);
enum
dma_data_direction
dir
=
fsi_stream_is_play
(
fsi
,
io
)
?
DMA_TO_DEVICE
:
DMA_FROM_DEVICE
;
dma_sync_single_for_cpu
(
dai
->
dev
,
fsi_dma_get_area
(
io
,
0
),
fsi_pointer_update
(
io
,
io
->
period_samples
);
samples_to_bytes
(
runtime
,
io
->
period_samples
),
dir
);
io
->
buff_sample_pos
+=
io
->
period_samples
;
io
->
period_pos
++
;
if
(
io
->
period_pos
>=
runtime
->
periods
)
{
io
->
period_pos
=
0
;
io
->
buff_sample_pos
=
0
;
}
fsi_count_fifo_err
(
fsi
);
fsi_count_fifo_err
(
fsi
);
fsi_stream_transfer
(
io
);
snd_pcm_period_elapsed
(
io
->
substream
);
}
}
static
void
fsi_dma_do_work
(
struct
work_struct
*
work
)
static
int
fsi_dma_transfer
(
struct
fsi_priv
*
fsi
,
struct
fsi_stream
*
io
)
{
{
struct
fsi_stream
*
io
=
container_of
(
work
,
struct
fsi_stream
,
work
);
struct
snd_soc_dai
*
dai
=
fsi_get_dai
(
io
->
substream
);
struct
fsi_priv
*
fsi
=
fsi_stream_to_priv
(
io
);
struct
snd_pcm_substream
*
substream
=
io
->
substream
;
struct
snd_soc_dai
*
dai
;
struct
dma_async_tx_descriptor
*
desc
;
struct
dma_async_tx_descriptor
*
desc
;
struct
snd_pcm_runtime
*
runtime
;
enum
dma_data_direction
dir
;
int
is_play
=
fsi_stream_is_play
(
fsi
,
io
);
int
is_play
=
fsi_stream_is_play
(
fsi
,
io
);
int
len
,
i
;
enum
dma_data_direction
dir
=
is_play
?
DMA_TO_DEVICE
:
DMA_FROM_DEVICE
;
dma_addr_t
buf
;
int
ret
=
-
EIO
;
if
(
!
fsi_stream_is_working
(
fsi
,
io
))
desc
=
dmaengine_prep_dma_cyclic
(
io
->
chan
,
return
;
substream
->
runtime
->
dma_addr
,
snd_pcm_lib_buffer_bytes
(
substream
),
dai
=
fsi_get_dai
(
io
->
substream
);
snd_pcm_lib_period_bytes
(
substream
),
runtime
=
io
->
substream
->
runtime
;
dir
,
dir
=
is_play
?
DMA_TO_DEVICE
:
DMA_FROM_DEVICE
;
len
=
samples_to_bytes
(
runtime
,
io
->
period_samples
);
for
(
i
=
0
;
i
<
io
->
loop_cnt
;
i
++
)
{
buf
=
fsi_dma_get_area
(
io
,
io
->
additional_pos
);
dma_sync_single_for_device
(
dai
->
dev
,
buf
,
len
,
dir
);
desc
=
dmaengine_prep_slave_single
(
io
->
chan
,
buf
,
len
,
dir
,
DMA_PREP_INTERRUPT
|
DMA_CTRL_ACK
);
DMA_PREP_INTERRUPT
|
DMA_CTRL_ACK
);
if
(
!
desc
)
{
if
(
!
desc
)
{
dev_err
(
dai
->
dev
,
"dmaengine_prep_slave_sg
() fail
\n
"
);
dev_err
(
dai
->
dev
,
"dmaengine_prep_dma_cyclic
() fail
\n
"
);
return
;
goto
fsi_dma_transfer_err
;
}
}
desc
->
callback
=
fsi_dma_complete
;
desc
->
callback
=
fsi_dma_complete
;
...
@@ -1383,16 +1316,11 @@ static void fsi_dma_do_work(struct work_struct *work)
...
@@ -1383,16 +1316,11 @@ static void fsi_dma_do_work(struct work_struct *work)
if
(
dmaengine_submit
(
desc
)
<
0
)
{
if
(
dmaengine_submit
(
desc
)
<
0
)
{
dev_err
(
dai
->
dev
,
"tx_submit() fail
\n
"
);
dev_err
(
dai
->
dev
,
"tx_submit() fail
\n
"
);
return
;
goto
fsi_dma_transfer_err
;
}
}
dma_async_issue_pending
(
io
->
chan
);
dma_async_issue_pending
(
io
->
chan
);
io
->
additional_pos
=
1
;
}
io
->
loop_cnt
=
1
;
/*
/*
* FIXME
* FIXME
*
*
...
@@ -1408,13 +1336,11 @@ static void fsi_dma_do_work(struct work_struct *work)
...
@@ -1408,13 +1336,11 @@ static void fsi_dma_do_work(struct work_struct *work)
fsi_reg_write
(
fsi
,
DIFF_ST
,
0
);
fsi_reg_write
(
fsi
,
DIFF_ST
,
0
);
}
}
}
}
}
static
int
fsi_dma_transfer
(
struct
fsi_priv
*
fsi
,
struct
fsi_stream
*
io
)
ret
=
0
;
{
schedule_work
(
&
io
->
work
);
return
0
;
fsi_dma_transfer_err:
return
ret
;
}
}
static
int
fsi_dma_push_start_stop
(
struct
fsi_priv
*
fsi
,
struct
fsi_stream
*
io
,
static
int
fsi_dma_push_start_stop
(
struct
fsi_priv
*
fsi
,
struct
fsi_stream
*
io
,
...
@@ -1475,15 +1401,11 @@ static int fsi_dma_probe(struct fsi_priv *fsi, struct fsi_stream *io, struct dev
...
@@ -1475,15 +1401,11 @@ static int fsi_dma_probe(struct fsi_priv *fsi, struct fsi_stream *io, struct dev
return
fsi_stream_probe
(
fsi
,
dev
);
return
fsi_stream_probe
(
fsi
,
dev
);
}
}
INIT_WORK
(
&
io
->
work
,
fsi_dma_do_work
);
return
0
;
return
0
;
}
}
static
int
fsi_dma_remove
(
struct
fsi_priv
*
fsi
,
struct
fsi_stream
*
io
)
static
int
fsi_dma_remove
(
struct
fsi_priv
*
fsi
,
struct
fsi_stream
*
io
)
{
{
cancel_work_sync
(
&
io
->
work
);
fsi_stream_stop
(
fsi
,
io
);
fsi_stream_stop
(
fsi
,
io
);
if
(
io
->
chan
)
if
(
io
->
chan
)
...
@@ -1495,7 +1417,6 @@ static int fsi_dma_remove(struct fsi_priv *fsi, struct fsi_stream *io)
...
@@ -1495,7 +1417,6 @@ static int fsi_dma_remove(struct fsi_priv *fsi, struct fsi_stream *io)
static
struct
fsi_stream_handler
fsi_dma_push_handler
=
{
static
struct
fsi_stream_handler
fsi_dma_push_handler
=
{
.
init
=
fsi_dma_init
,
.
init
=
fsi_dma_init
,
.
quit
=
fsi_dma_quit
,
.
probe
=
fsi_dma_probe
,
.
probe
=
fsi_dma_probe
,
.
transfer
=
fsi_dma_transfer
,
.
transfer
=
fsi_dma_transfer
,
.
remove
=
fsi_dma_remove
,
.
remove
=
fsi_dma_remove
,
...
@@ -1657,9 +1578,9 @@ static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd,
...
@@ -1657,9 +1578,9 @@ static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd,
if
(
!
ret
)
if
(
!
ret
)
ret
=
fsi_hw_startup
(
fsi
,
io
,
dai
->
dev
);
ret
=
fsi_hw_startup
(
fsi
,
io
,
dai
->
dev
);
if
(
!
ret
)
if
(
!
ret
)
ret
=
fsi_stream_
transfer
(
io
);
ret
=
fsi_stream_
start
(
fsi
,
io
);
if
(
!
ret
)
if
(
!
ret
)
fsi_stream_start
(
fsi
,
io
);
ret
=
fsi_stream_transfer
(
io
);
break
;
break
;
case
SNDRV_PCM_TRIGGER_STOP
:
case
SNDRV_PCM_TRIGGER_STOP
:
if
(
!
ret
)
if
(
!
ret
)
...
@@ -1850,16 +1771,10 @@ static void fsi_pcm_free(struct snd_pcm *pcm)
...
@@ -1850,16 +1771,10 @@ static void fsi_pcm_free(struct snd_pcm *pcm)
static
int
fsi_pcm_new
(
struct
snd_soc_pcm_runtime
*
rtd
)
static
int
fsi_pcm_new
(
struct
snd_soc_pcm_runtime
*
rtd
)
{
{
struct
snd_pcm
*
pcm
=
rtd
->
pcm
;
/*
* dont use SNDRV_DMA_TYPE_DEV, since it will oops the SH kernel
* in MMAP mode (i.e. aplay -M)
*/
return
snd_pcm_lib_preallocate_pages_for_all
(
return
snd_pcm_lib_preallocate_pages_for_all
(
pcm
,
rtd
->
pcm
,
SNDRV_DMA_TYPE_
CONTINUOUS
,
SNDRV_DMA_TYPE_
DEV
,
snd_dma_continuous_data
(
GFP_KERNEL
)
,
rtd
->
card
->
snd_card
->
dev
,
PREALLOC_BUFFER
,
PREALLOC_BUFFER_MAX
);
PREALLOC_BUFFER
,
PREALLOC_BUFFER_MAX
);
}
}
...
...
sound/soc/sh/rcar/core.c
浏览文件 @
2fd53734
...
@@ -138,6 +138,17 @@ char *rsnd_mod_name(struct rsnd_mod *mod)
...
@@ -138,6 +138,17 @@ char *rsnd_mod_name(struct rsnd_mod *mod)
return
mod
->
ops
->
name
;
return
mod
->
ops
->
name
;
}
}
char
*
rsnd_mod_dma_name
(
struct
rsnd_mod
*
mod
)
{
if
(
!
mod
||
!
mod
->
ops
)
return
"unknown"
;
if
(
!
mod
->
ops
->
dma_name
)
return
mod
->
ops
->
name
;
return
mod
->
ops
->
dma_name
(
mod
);
}
void
rsnd_mod_init
(
struct
rsnd_priv
*
priv
,
void
rsnd_mod_init
(
struct
rsnd_priv
*
priv
,
struct
rsnd_mod
*
mod
,
struct
rsnd_mod
*
mod
,
struct
rsnd_mod_ops
*
ops
,
struct
rsnd_mod_ops
*
ops
,
...
@@ -153,26 +164,8 @@ void rsnd_mod_init(struct rsnd_priv *priv,
...
@@ -153,26 +164,8 @@ void rsnd_mod_init(struct rsnd_priv *priv,
/*
/*
* rsnd_dma functions
* rsnd_dma functions
*/
*/
static
void
__rsnd_dma_start
(
struct
rsnd_dma
*
dma
);
static
void
rsnd_dma_continue
(
struct
rsnd_dma
*
dma
)
{
/* push next A or B plane */
dma
->
submit_loop
=
1
;
schedule_work
(
&
dma
->
work
);
}
void
rsnd_dma_start
(
struct
rsnd_dma
*
dma
)
{
/* push both A and B plane*/
dma
->
offset
=
0
;
dma
->
submit_loop
=
2
;
__rsnd_dma_start
(
dma
);
}
void
rsnd_dma_stop
(
struct
rsnd_dma
*
dma
)
void
rsnd_dma_stop
(
struct
rsnd_dma
*
dma
)
{
{
dma
->
submit_loop
=
0
;
cancel_work_sync
(
&
dma
->
work
);
dmaengine_terminate_all
(
dma
->
chan
);
dmaengine_terminate_all
(
dma
->
chan
);
}
}
...
@@ -180,11 +173,7 @@ static void rsnd_dma_complete(void *data)
...
@@ -180,11 +173,7 @@ static void rsnd_dma_complete(void *data)
{
{
struct
rsnd_dma
*
dma
=
(
struct
rsnd_dma
*
)
data
;
struct
rsnd_dma
*
dma
=
(
struct
rsnd_dma
*
)
data
;
struct
rsnd_mod
*
mod
=
rsnd_dma_to_mod
(
dma
);
struct
rsnd_mod
*
mod
=
rsnd_dma_to_mod
(
dma
);
struct
rsnd_priv
*
priv
=
rsnd_mod_to_priv
(
rsnd_dma_to_mod
(
dma
));
struct
rsnd_dai_stream
*
io
=
rsnd_mod_to_io
(
mod
);
struct
rsnd_dai_stream
*
io
=
rsnd_mod_to_io
(
mod
);
unsigned
long
flags
;
rsnd_lock
(
priv
,
flags
);
/*
/*
* Renesas sound Gen1 needs 1 DMAC,
* Renesas sound Gen1 needs 1 DMAC,
...
@@ -197,35 +186,27 @@ static void rsnd_dma_complete(void *data)
...
@@ -197,35 +186,27 @@ static void rsnd_dma_complete(void *data)
* rsnd_dai_pointer_update() will be called twice,
* rsnd_dai_pointer_update() will be called twice,
* ant it will breaks io->byte_pos
* ant it will breaks io->byte_pos
*/
*/
if
(
dma
->
submit_loop
)
rsnd_dma_continue
(
dma
);
rsnd_unlock
(
priv
,
flags
);
rsnd_dai_pointer_update
(
io
,
io
->
byte_per_period
);
rsnd_dai_pointer_update
(
io
,
io
->
byte_per_period
);
}
}
static
void
__
rsnd_dma_start
(
struct
rsnd_dma
*
dma
)
void
rsnd_dma_start
(
struct
rsnd_dma
*
dma
)
{
{
struct
rsnd_mod
*
mod
=
rsnd_dma_to_mod
(
dma
);
struct
rsnd_mod
*
mod
=
rsnd_dma_to_mod
(
dma
);
struct
rsnd_priv
*
priv
=
rsnd_mod_to_priv
(
mod
);
struct
rsnd_priv
*
priv
=
rsnd_mod_to_priv
(
mod
);
struct
rsnd_dai_stream
*
io
=
rsnd_mod_to_io
(
mod
);
struct
rsnd_dai_stream
*
io
=
rsnd_mod_to_io
(
mod
);
struct
snd_pcm_
runtime
*
runtime
=
rsnd_io_to_runtime
(
io
)
;
struct
snd_pcm_
substream
*
substream
=
io
->
substream
;
struct
device
*
dev
=
rsnd_priv_to_dev
(
priv
);
struct
device
*
dev
=
rsnd_priv_to_dev
(
priv
);
struct
dma_async_tx_descriptor
*
desc
;
struct
dma_async_tx_descriptor
*
desc
;
dma_addr_t
buf
;
size_t
len
=
io
->
byte_per_period
;
int
i
;
for
(
i
=
0
;
i
<
dma
->
submit_loop
;
i
++
)
{
desc
=
dmaengine_prep_dma_cyclic
(
dma
->
chan
,
(
dma
->
addr
)
?
dma
->
addr
:
buf
=
runtime
->
dma_addr
+
substream
->
runtime
->
dma_addr
,
rsnd_dai_pointer_offset
(
io
,
dma
->
offset
+
len
);
snd_pcm_lib_buffer_bytes
(
substream
),
dma
->
offset
=
len
;
snd_pcm_lib_period_bytes
(
substream
),
dma
->
dir
,
desc
=
dmaengine_prep_slave_single
(
dma
->
chan
,
buf
,
len
,
dma
->
dir
,
DMA_PREP_INTERRUPT
|
DMA_CTRL_ACK
);
DMA_PREP_INTERRUPT
|
DMA_CTRL_ACK
);
if
(
!
desc
)
{
if
(
!
desc
)
{
dev_err
(
dev
,
"dmaengine_prep_slave_sg() fail
\n
"
);
dev_err
(
dev
,
"dmaengine_prep_slave_sg() fail
\n
"
);
return
;
return
;
...
@@ -240,14 +221,6 @@ static void __rsnd_dma_start(struct rsnd_dma *dma)
...
@@ -240,14 +221,6 @@ static void __rsnd_dma_start(struct rsnd_dma *dma)
}
}
dma_async_issue_pending
(
dma
->
chan
);
dma_async_issue_pending
(
dma
->
chan
);
}
}
static
void
rsnd_dma_do_work
(
struct
work_struct
*
work
)
{
struct
rsnd_dma
*
dma
=
container_of
(
work
,
struct
rsnd_dma
,
work
);
__rsnd_dma_start
(
dma
);
}
}
int
rsnd_dma_available
(
struct
rsnd_dma
*
dma
)
int
rsnd_dma_available
(
struct
rsnd_dma
*
dma
)
...
@@ -261,14 +234,27 @@ static int _rsnd_dma_of_name(char *dma_name, struct rsnd_mod *mod)
...
@@ -261,14 +234,27 @@ static int _rsnd_dma_of_name(char *dma_name, struct rsnd_mod *mod)
{
{
if
(
mod
)
if
(
mod
)
return
snprintf
(
dma_name
,
DMA_NAME_SIZE
/
2
,
"%s%d"
,
return
snprintf
(
dma_name
,
DMA_NAME_SIZE
/
2
,
"%s%d"
,
rsnd_mod_name
(
mod
),
rsnd_mod_id
(
mod
));
rsnd_mod_
dma_
name
(
mod
),
rsnd_mod_id
(
mod
));
else
else
return
snprintf
(
dma_name
,
DMA_NAME_SIZE
/
2
,
"mem"
);
return
snprintf
(
dma_name
,
DMA_NAME_SIZE
/
2
,
"mem"
);
}
}
static
void
rsnd_dma_of_name
(
struct
rsnd_dma
*
dma
,
static
void
rsnd_dma_of_name
(
struct
rsnd_mod
*
mod_from
,
int
is_play
,
char
*
dma_name
)
struct
rsnd_mod
*
mod_to
,
char
*
dma_name
)
{
int
index
=
0
;
index
=
_rsnd_dma_of_name
(
dma_name
+
index
,
mod_from
);
*
(
dma_name
+
index
++
)
=
'_'
;
index
=
_rsnd_dma_of_name
(
dma_name
+
index
,
mod_to
);
}
static
void
rsnd_dma_of_path
(
struct
rsnd_dma
*
dma
,
int
is_play
,
struct
rsnd_mod
**
mod_from
,
struct
rsnd_mod
**
mod_to
)
{
{
struct
rsnd_mod
*
this
=
rsnd_dma_to_mod
(
dma
);
struct
rsnd_mod
*
this
=
rsnd_dma_to_mod
(
dma
);
struct
rsnd_dai_stream
*
io
=
rsnd_mod_to_io
(
this
);
struct
rsnd_dai_stream
*
io
=
rsnd_mod_to_io
(
this
);
...
@@ -276,7 +262,6 @@ static void rsnd_dma_of_name(struct rsnd_dma *dma,
...
@@ -276,7 +262,6 @@ static void rsnd_dma_of_name(struct rsnd_dma *dma,
struct
rsnd_mod
*
src
=
rsnd_io_to_mod_src
(
io
);
struct
rsnd_mod
*
src
=
rsnd_io_to_mod_src
(
io
);
struct
rsnd_mod
*
dvc
=
rsnd_io_to_mod_dvc
(
io
);
struct
rsnd_mod
*
dvc
=
rsnd_io_to_mod_dvc
(
io
);
struct
rsnd_mod
*
mod
[
MOD_MAX
];
struct
rsnd_mod
*
mod
[
MOD_MAX
];
struct
rsnd_mod
*
src_mod
,
*
dst_mod
;
int
i
,
index
;
int
i
,
index
;
...
@@ -301,7 +286,13 @@ static void rsnd_dma_of_name(struct rsnd_dma *dma,
...
@@ -301,7 +286,13 @@ static void rsnd_dma_of_name(struct rsnd_dma *dma,
mod
[
i
]
=
src
;
mod
[
i
]
=
src
;
src
=
NULL
;
src
=
NULL
;
}
else
{
}
else
{
mod
[
i
]
=
dvc
;
if
((
!
is_play
)
&&
(
this
==
src
))
this
=
dvc
;
mod
[
i
]
=
(
is_play
)
?
src
:
dvc
;
i
++
;
mod
[
i
]
=
(
is_play
)
?
dvc
:
src
;
src
=
NULL
;
dvc
=
NULL
;
dvc
=
NULL
;
}
}
...
@@ -313,17 +304,12 @@ static void rsnd_dma_of_name(struct rsnd_dma *dma,
...
@@ -313,17 +304,12 @@ static void rsnd_dma_of_name(struct rsnd_dma *dma,
}
}
if
(
is_play
)
{
if
(
is_play
)
{
src_mod
=
mod
[
index
-
1
];
*
mod_from
=
mod
[
index
-
1
];
dst_mod
=
mod
[
index
];
*
mod_to
=
mod
[
index
];
}
else
{
}
else
{
src_mod
=
mod
[
index
];
*
mod_from
=
mod
[
index
];
dst_mod
=
mod
[
index
-
1
];
*
mod_to
=
mod
[
index
-
1
];
}
}
index
=
0
;
index
=
_rsnd_dma_of_name
(
dma_name
+
index
,
src_mod
);
*
(
dma_name
+
index
++
)
=
'_'
;
index
=
_rsnd_dma_of_name
(
dma_name
+
index
,
dst_mod
);
}
}
int
rsnd_dma_init
(
struct
rsnd_priv
*
priv
,
struct
rsnd_dma
*
dma
,
int
rsnd_dma_init
(
struct
rsnd_priv
*
priv
,
struct
rsnd_dma
*
dma
,
...
@@ -331,6 +317,8 @@ int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma,
...
@@ -331,6 +317,8 @@ int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma,
{
{
struct
device
*
dev
=
rsnd_priv_to_dev
(
priv
);
struct
device
*
dev
=
rsnd_priv_to_dev
(
priv
);
struct
dma_slave_config
cfg
;
struct
dma_slave_config
cfg
;
struct
rsnd_mod
*
mod_from
;
struct
rsnd_mod
*
mod_to
;
char
dma_name
[
DMA_NAME_SIZE
];
char
dma_name
[
DMA_NAME_SIZE
];
dma_cap_mask_t
mask
;
dma_cap_mask_t
mask
;
int
ret
;
int
ret
;
...
@@ -343,13 +331,18 @@ int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma,
...
@@ -343,13 +331,18 @@ int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma,
dma_cap_zero
(
mask
);
dma_cap_zero
(
mask
);
dma_cap_set
(
DMA_SLAVE
,
mask
);
dma_cap_set
(
DMA_SLAVE
,
mask
);
if
(
dev
->
of_node
)
rsnd_dma_of_path
(
dma
,
is_play
,
&
mod_from
,
&
mod_to
);
rsnd_dma_of_name
(
dma
,
is_play
,
dma_name
);
rsnd_dma_of_name
(
mod_from
,
mod_to
,
dma_name
);
else
snprintf
(
dma_name
,
DMA_NAME_SIZE
,
is_play
?
"tx"
:
"rx"
);
dev_dbg
(
dev
,
"dma name : %s
\n
"
,
dma_name
);
cfg
.
slave_id
=
id
;
cfg
.
direction
=
is_play
?
DMA_MEM_TO_DEV
:
DMA_DEV_TO_MEM
;
cfg
.
src_addr
=
rsnd_gen_dma_addr
(
priv
,
mod_from
,
is_play
,
1
);
cfg
.
dst_addr
=
rsnd_gen_dma_addr
(
priv
,
mod_to
,
is_play
,
0
);
cfg
.
src_addr_width
=
DMA_SLAVE_BUSWIDTH_4_BYTES
;
cfg
.
dst_addr_width
=
DMA_SLAVE_BUSWIDTH_4_BYTES
;
dev_dbg
(
dev
,
"dma : %s %pad -> %pad
\n
"
,
dma_name
,
&
cfg
.
src_addr
,
&
cfg
.
dst_addr
);
dma
->
chan
=
dma_request_slave_channel_compat
(
mask
,
shdma_chan_filter
,
dma
->
chan
=
dma_request_slave_channel_compat
(
mask
,
shdma_chan_filter
,
(
void
*
)
id
,
dev
,
(
void
*
)
id
,
dev
,
...
@@ -359,14 +352,12 @@ int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma,
...
@@ -359,14 +352,12 @@ int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma,
return
-
EIO
;
return
-
EIO
;
}
}
rsnd_gen_dma_addr
(
priv
,
dma
,
&
cfg
,
is_play
,
id
);
ret
=
dmaengine_slave_config
(
dma
->
chan
,
&
cfg
);
ret
=
dmaengine_slave_config
(
dma
->
chan
,
&
cfg
);
if
(
ret
<
0
)
if
(
ret
<
0
)
goto
rsnd_dma_init_err
;
goto
rsnd_dma_init_err
;
dma
->
dir
=
is_play
?
DMA_TO_DEVICE
:
DMA_FROM_DEVICE
;
dma
->
addr
=
is_play
?
cfg
.
src_addr
:
cfg
.
dst_addr
;
INIT_WORK
(
&
dma
->
work
,
rsnd_dma_do_work
)
;
dma
->
dir
=
is_play
?
DMA_MEM_TO_DEV
:
DMA_DEV_TO_MEM
;
return
0
;
return
0
;
...
@@ -633,40 +624,41 @@ static int rsnd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
...
@@ -633,40 +624,41 @@ static int rsnd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
return
-
EINVAL
;
return
-
EINVAL
;
}
}
/* set clock inversion */
switch
(
fmt
&
SND_SOC_DAIFMT_INV_MASK
)
{
case
SND_SOC_DAIFMT_NB_IF
:
rdai
->
bit_clk_inv
=
0
;
rdai
->
frm_clk_inv
=
1
;
break
;
case
SND_SOC_DAIFMT_IB_NF
:
rdai
->
bit_clk_inv
=
1
;
rdai
->
frm_clk_inv
=
0
;
break
;
case
SND_SOC_DAIFMT_IB_IF
:
rdai
->
bit_clk_inv
=
1
;
rdai
->
frm_clk_inv
=
1
;
break
;
case
SND_SOC_DAIFMT_NB_NF
:
default:
rdai
->
bit_clk_inv
=
0
;
rdai
->
frm_clk_inv
=
0
;
break
;
}
/* set format */
/* set format */
switch
(
fmt
&
SND_SOC_DAIFMT_FORMAT_MASK
)
{
switch
(
fmt
&
SND_SOC_DAIFMT_FORMAT_MASK
)
{
case
SND_SOC_DAIFMT_I2S
:
case
SND_SOC_DAIFMT_I2S
:
rdai
->
sys_delay
=
0
;
rdai
->
sys_delay
=
0
;
rdai
->
data_alignment
=
0
;
rdai
->
data_alignment
=
0
;
rdai
->
frm_clk_inv
=
0
;
break
;
break
;
case
SND_SOC_DAIFMT_LEFT_J
:
case
SND_SOC_DAIFMT_LEFT_J
:
rdai
->
sys_delay
=
1
;
rdai
->
sys_delay
=
1
;
rdai
->
data_alignment
=
0
;
rdai
->
data_alignment
=
0
;
rdai
->
frm_clk_inv
=
1
;
break
;
break
;
case
SND_SOC_DAIFMT_RIGHT_J
:
case
SND_SOC_DAIFMT_RIGHT_J
:
rdai
->
sys_delay
=
1
;
rdai
->
sys_delay
=
1
;
rdai
->
data_alignment
=
1
;
rdai
->
data_alignment
=
1
;
rdai
->
frm_clk_inv
=
1
;
break
;
}
/* set clock inversion */
switch
(
fmt
&
SND_SOC_DAIFMT_INV_MASK
)
{
case
SND_SOC_DAIFMT_NB_IF
:
rdai
->
bit_clk_inv
=
rdai
->
bit_clk_inv
;
rdai
->
frm_clk_inv
=
!
rdai
->
frm_clk_inv
;
break
;
case
SND_SOC_DAIFMT_IB_NF
:
rdai
->
bit_clk_inv
=
!
rdai
->
bit_clk_inv
;
rdai
->
frm_clk_inv
=
rdai
->
frm_clk_inv
;
break
;
case
SND_SOC_DAIFMT_IB_IF
:
rdai
->
bit_clk_inv
=
!
rdai
->
bit_clk_inv
;
rdai
->
frm_clk_inv
=
!
rdai
->
frm_clk_inv
;
break
;
case
SND_SOC_DAIFMT_NB_NF
:
default:
break
;
break
;
}
}
...
@@ -736,12 +728,13 @@ static void rsnd_of_parse_dai(struct platform_device *pdev,
...
@@ -736,12 +728,13 @@ static void rsnd_of_parse_dai(struct platform_device *pdev,
struct
device_node
*
dai_node
,
*
dai_np
;
struct
device_node
*
dai_node
,
*
dai_np
;
struct
device_node
*
ssi_node
,
*
ssi_np
;
struct
device_node
*
ssi_node
,
*
ssi_np
;
struct
device_node
*
src_node
,
*
src_np
;
struct
device_node
*
src_node
,
*
src_np
;
struct
device_node
*
dvc_node
,
*
dvc_np
;
struct
device_node
*
playback
,
*
capture
;
struct
device_node
*
playback
,
*
capture
;
struct
rsnd_dai_platform_info
*
dai_info
;
struct
rsnd_dai_platform_info
*
dai_info
;
struct
rcar_snd_info
*
info
=
rsnd_priv_to_info
(
priv
);
struct
rcar_snd_info
*
info
=
rsnd_priv_to_info
(
priv
);
struct
device
*
dev
=
&
pdev
->
dev
;
struct
device
*
dev
=
&
pdev
->
dev
;
int
nr
,
i
;
int
nr
,
i
;
int
dai_i
,
ssi_i
,
src_i
;
int
dai_i
,
ssi_i
,
src_i
,
dvc_i
;
if
(
!
of_data
)
if
(
!
of_data
)
return
;
return
;
...
@@ -767,6 +760,7 @@ static void rsnd_of_parse_dai(struct platform_device *pdev,
...
@@ -767,6 +760,7 @@ static void rsnd_of_parse_dai(struct platform_device *pdev,
ssi_node
=
of_get_child_by_name
(
dev
->
of_node
,
"rcar_sound,ssi"
);
ssi_node
=
of_get_child_by_name
(
dev
->
of_node
,
"rcar_sound,ssi"
);
src_node
=
of_get_child_by_name
(
dev
->
of_node
,
"rcar_sound,src"
);
src_node
=
of_get_child_by_name
(
dev
->
of_node
,
"rcar_sound,src"
);
dvc_node
=
of_get_child_by_name
(
dev
->
of_node
,
"rcar_sound,dvc"
);
#define mod_parse(name) \
#define mod_parse(name) \
if (name##_node) { \
if (name##_node) { \
...
@@ -802,6 +796,7 @@ if (name##_node) { \
...
@@ -802,6 +796,7 @@ if (name##_node) { \
mod_parse
(
ssi
);
mod_parse
(
ssi
);
mod_parse
(
src
);
mod_parse
(
src
);
mod_parse
(
dvc
);
if
(
playback
)
if
(
playback
)
of_node_put
(
playback
);
of_node_put
(
playback
);
...
@@ -950,11 +945,10 @@ static struct snd_pcm_ops rsnd_pcm_ops = {
...
@@ -950,11 +945,10 @@ static struct snd_pcm_ops rsnd_pcm_ops = {
static
int
rsnd_pcm_new
(
struct
snd_soc_pcm_runtime
*
rtd
)
static
int
rsnd_pcm_new
(
struct
snd_soc_pcm_runtime
*
rtd
)
{
{
struct
rsnd_priv
*
priv
=
snd_soc_dai_get_drvdata
(
rtd
->
cpu_dai
)
;
struct
snd_soc_dai
*
dai
=
rtd
->
cpu_dai
;
struct
rsnd_dai
*
rdai
;
struct
rsnd_dai
*
rdai
=
rsnd_dai_to_rdai
(
dai
)
;
int
i
,
ret
;
int
ret
;
for_each_rsnd_dai
(
rdai
,
priv
,
i
)
{
ret
=
rsnd_dai_call
(
pcm_new
,
&
rdai
->
playback
,
rdai
,
rtd
);
ret
=
rsnd_dai_call
(
pcm_new
,
&
rdai
->
playback
,
rdai
,
rtd
);
if
(
ret
)
if
(
ret
)
return
ret
;
return
ret
;
...
@@ -962,7 +956,6 @@ static int rsnd_pcm_new(struct snd_soc_pcm_runtime *rtd)
...
@@ -962,7 +956,6 @@ static int rsnd_pcm_new(struct snd_soc_pcm_runtime *rtd)
ret
=
rsnd_dai_call
(
pcm_new
,
&
rdai
->
capture
,
rdai
,
rtd
);
ret
=
rsnd_dai_call
(
pcm_new
,
&
rdai
->
capture
,
rdai
,
rtd
);
if
(
ret
)
if
(
ret
)
return
ret
;
return
ret
;
}
return
snd_pcm_lib_preallocate_pages_for_all
(
return
snd_pcm_lib_preallocate_pages_for_all
(
rtd
->
pcm
,
rtd
->
pcm
,
...
@@ -1049,11 +1042,11 @@ static int rsnd_probe(struct platform_device *pdev)
...
@@ -1049,11 +1042,11 @@ static int rsnd_probe(struct platform_device *pdev)
for_each_rsnd_dai
(
rdai
,
priv
,
i
)
{
for_each_rsnd_dai
(
rdai
,
priv
,
i
)
{
ret
=
rsnd_dai_call
(
probe
,
&
rdai
->
playback
,
rdai
);
ret
=
rsnd_dai_call
(
probe
,
&
rdai
->
playback
,
rdai
);
if
(
ret
)
if
(
ret
)
return
ret
;
goto
exit_snd_probe
;
ret
=
rsnd_dai_call
(
probe
,
&
rdai
->
capture
,
rdai
);
ret
=
rsnd_dai_call
(
probe
,
&
rdai
->
capture
,
rdai
);
if
(
ret
)
if
(
ret
)
return
ret
;
goto
exit_snd_probe
;
}
}
/*
/*
...
@@ -1081,6 +1074,11 @@ static int rsnd_probe(struct platform_device *pdev)
...
@@ -1081,6 +1074,11 @@ static int rsnd_probe(struct platform_device *pdev)
exit_snd_soc:
exit_snd_soc:
snd_soc_unregister_platform
(
dev
);
snd_soc_unregister_platform
(
dev
);
exit_snd_probe:
for_each_rsnd_dai
(
rdai
,
priv
,
i
)
{
rsnd_dai_call
(
remove
,
&
rdai
->
playback
,
rdai
);
rsnd_dai_call
(
remove
,
&
rdai
->
capture
,
rdai
);
}
return
ret
;
return
ret
;
}
}
...
@@ -1089,21 +1087,16 @@ static int rsnd_remove(struct platform_device *pdev)
...
@@ -1089,21 +1087,16 @@ static int rsnd_remove(struct platform_device *pdev)
{
{
struct
rsnd_priv
*
priv
=
dev_get_drvdata
(
&
pdev
->
dev
);
struct
rsnd_priv
*
priv
=
dev_get_drvdata
(
&
pdev
->
dev
);
struct
rsnd_dai
*
rdai
;
struct
rsnd_dai
*
rdai
;
int
ret
,
i
;
int
ret
=
0
,
i
;
pm_runtime_disable
(
&
pdev
->
dev
);
pm_runtime_disable
(
&
pdev
->
dev
);
for_each_rsnd_dai
(
rdai
,
priv
,
i
)
{
for_each_rsnd_dai
(
rdai
,
priv
,
i
)
{
ret
=
rsnd_dai_call
(
remove
,
&
rdai
->
playback
,
rdai
);
ret
|=
rsnd_dai_call
(
remove
,
&
rdai
->
playback
,
rdai
);
if
(
ret
)
ret
|=
rsnd_dai_call
(
remove
,
&
rdai
->
capture
,
rdai
);
return
ret
;
ret
=
rsnd_dai_call
(
remove
,
&
rdai
->
capture
,
rdai
);
if
(
ret
)
return
ret
;
}
}
return
0
;
return
ret
;
}
}
static
struct
platform_driver
rsnd_driver
=
{
static
struct
platform_driver
rsnd_driver
=
{
...
...
sound/soc/sh/rcar/dvc.c
浏览文件 @
2fd53734
...
@@ -20,7 +20,8 @@ struct rsnd_dvc {
...
@@ -20,7 +20,8 @@ struct rsnd_dvc {
struct
rsnd_dvc_platform_info
*
info
;
/* rcar_snd.h */
struct
rsnd_dvc_platform_info
*
info
;
/* rcar_snd.h */
struct
rsnd_mod
mod
;
struct
rsnd_mod
mod
;
struct
clk
*
clk
;
struct
clk
*
clk
;
long
volume
[
RSND_DVC_VOLUME_NUM
];
u8
volume
[
RSND_DVC_VOLUME_NUM
];
u8
mute
[
RSND_DVC_VOLUME_NUM
];
};
};
#define rsnd_mod_to_dvc(_mod) \
#define rsnd_mod_to_dvc(_mod) \
...
@@ -37,13 +38,18 @@ static void rsnd_dvc_volume_update(struct rsnd_mod *mod)
...
@@ -37,13 +38,18 @@ static void rsnd_dvc_volume_update(struct rsnd_mod *mod)
struct
rsnd_dvc
*
dvc
=
rsnd_mod_to_dvc
(
mod
);
struct
rsnd_dvc
*
dvc
=
rsnd_mod_to_dvc
(
mod
);
u32
max
=
(
0x00800000
-
1
);
u32
max
=
(
0x00800000
-
1
);
u32
vol
[
RSND_DVC_VOLUME_NUM
];
u32
vol
[
RSND_DVC_VOLUME_NUM
];
u32
mute
=
0
;
int
i
;
int
i
;
for
(
i
=
0
;
i
<
RSND_DVC_VOLUME_NUM
;
i
++
)
for
(
i
=
0
;
i
<
RSND_DVC_VOLUME_NUM
;
i
++
)
{
vol
[
i
]
=
max
/
RSND_DVC_VOLUME_MAX
*
dvc
->
volume
[
i
];
vol
[
i
]
=
max
/
RSND_DVC_VOLUME_MAX
*
dvc
->
volume
[
i
];
mute
|=
(
!!
dvc
->
mute
[
i
])
<<
i
;
}
rsnd_mod_write
(
mod
,
DVC_VOL0R
,
vol
[
0
]);
rsnd_mod_write
(
mod
,
DVC_VOL0R
,
vol
[
0
]);
rsnd_mod_write
(
mod
,
DVC_VOL1R
,
vol
[
1
]);
rsnd_mod_write
(
mod
,
DVC_VOL1R
,
vol
[
1
]);
rsnd_mod_write
(
mod
,
DVC_ZCMCR
,
mute
);
}
}
static
int
rsnd_dvc_probe_gen2
(
struct
rsnd_mod
*
mod
,
static
int
rsnd_dvc_probe_gen2
(
struct
rsnd_mod
*
mod
,
...
@@ -96,8 +102,8 @@ static int rsnd_dvc_init(struct rsnd_mod *dvc_mod,
...
@@ -96,8 +102,8 @@ static int rsnd_dvc_init(struct rsnd_mod *dvc_mod,
rsnd_mod_write
(
dvc_mod
,
DVC_ADINR
,
rsnd_get_adinr
(
dvc_mod
));
rsnd_mod_write
(
dvc_mod
,
DVC_ADINR
,
rsnd_get_adinr
(
dvc_mod
));
/* enable Volume */
/* enable Volume
/ Mute
*/
rsnd_mod_write
(
dvc_mod
,
DVC_DVUCR
,
0x10
0
);
rsnd_mod_write
(
dvc_mod
,
DVC_DVUCR
,
0x10
1
);
/* ch0/ch1 Volume */
/* ch0/ch1 Volume */
rsnd_dvc_volume_update
(
dvc_mod
);
rsnd_dvc_volume_update
(
dvc_mod
);
...
@@ -140,10 +146,20 @@ static int rsnd_dvc_stop(struct rsnd_mod *mod,
...
@@ -140,10 +146,20 @@ static int rsnd_dvc_stop(struct rsnd_mod *mod,
static
int
rsnd_dvc_volume_info
(
struct
snd_kcontrol
*
kctrl
,
static
int
rsnd_dvc_volume_info
(
struct
snd_kcontrol
*
kctrl
,
struct
snd_ctl_elem_info
*
uinfo
)
struct
snd_ctl_elem_info
*
uinfo
)
{
{
uinfo
->
type
=
SNDRV_CTL_ELEM_TYPE_INTEGER
;
struct
rsnd_mod
*
mod
=
snd_kcontrol_chip
(
kctrl
);
struct
rsnd_dvc
*
dvc
=
rsnd_mod_to_dvc
(
mod
);
u8
*
val
=
(
u8
*
)
kctrl
->
private_value
;
uinfo
->
count
=
RSND_DVC_VOLUME_NUM
;
uinfo
->
count
=
RSND_DVC_VOLUME_NUM
;
uinfo
->
value
.
integer
.
min
=
0
;
uinfo
->
value
.
integer
.
min
=
0
;
if
(
val
==
dvc
->
volume
)
{
uinfo
->
type
=
SNDRV_CTL_ELEM_TYPE_INTEGER
;
uinfo
->
value
.
integer
.
max
=
RSND_DVC_VOLUME_MAX
;
uinfo
->
value
.
integer
.
max
=
RSND_DVC_VOLUME_MAX
;
}
else
{
uinfo
->
type
=
SNDRV_CTL_ELEM_TYPE_BOOLEAN
;
uinfo
->
value
.
integer
.
max
=
1
;
}
return
0
;
return
0
;
}
}
...
@@ -151,12 +167,11 @@ static int rsnd_dvc_volume_info(struct snd_kcontrol *kctrl,
...
@@ -151,12 +167,11 @@ static int rsnd_dvc_volume_info(struct snd_kcontrol *kctrl,
static
int
rsnd_dvc_volume_get
(
struct
snd_kcontrol
*
kctrl
,
static
int
rsnd_dvc_volume_get
(
struct
snd_kcontrol
*
kctrl
,
struct
snd_ctl_elem_value
*
ucontrol
)
struct
snd_ctl_elem_value
*
ucontrol
)
{
{
struct
rsnd_mod
*
mod
=
snd_kcontrol_chip
(
kctrl
);
u8
*
val
=
(
u8
*
)
kctrl
->
private_value
;
struct
rsnd_dvc
*
dvc
=
rsnd_mod_to_dvc
(
mod
);
int
i
;
int
i
;
for
(
i
=
0
;
i
<
RSND_DVC_VOLUME_NUM
;
i
++
)
for
(
i
=
0
;
i
<
RSND_DVC_VOLUME_NUM
;
i
++
)
ucontrol
->
value
.
integer
.
value
[
i
]
=
dvc
->
volume
[
i
];
ucontrol
->
value
.
integer
.
value
[
i
]
=
val
[
i
];
return
0
;
return
0
;
}
}
...
@@ -165,51 +180,38 @@ static int rsnd_dvc_volume_put(struct snd_kcontrol *kctrl,
...
@@ -165,51 +180,38 @@ static int rsnd_dvc_volume_put(struct snd_kcontrol *kctrl,
struct
snd_ctl_elem_value
*
ucontrol
)
struct
snd_ctl_elem_value
*
ucontrol
)
{
{
struct
rsnd_mod
*
mod
=
snd_kcontrol_chip
(
kctrl
);
struct
rsnd_mod
*
mod
=
snd_kcontrol_chip
(
kctrl
);
struct
rsnd_dvc
*
dvc
=
rsnd_mod_to_dvc
(
mod
)
;
u8
*
val
=
(
u8
*
)
kctrl
->
private_value
;
int
i
,
change
=
0
;
int
i
,
change
=
0
;
for
(
i
=
0
;
i
<
RSND_DVC_VOLUME_NUM
;
i
++
)
{
for
(
i
=
0
;
i
<
RSND_DVC_VOLUME_NUM
;
i
++
)
{
if
(
ucontrol
->
value
.
integer
.
value
[
i
]
<
0
||
change
|=
(
ucontrol
->
value
.
integer
.
value
[
i
]
!=
val
[
i
]);
ucontrol
->
value
.
integer
.
value
[
i
]
>
RSND_DVC_VOLUME_MAX
)
val
[
i
]
=
ucontrol
->
value
.
integer
.
value
[
i
];
return
-
EINVAL
;
change
|=
(
ucontrol
->
value
.
integer
.
value
[
i
]
!=
dvc
->
volume
[
i
]);
}
}
if
(
change
)
{
if
(
change
)
for
(
i
=
0
;
i
<
RSND_DVC_VOLUME_NUM
;
i
++
)
dvc
->
volume
[
i
]
=
ucontrol
->
value
.
integer
.
value
[
i
];
rsnd_dvc_volume_update
(
mod
);
rsnd_dvc_volume_update
(
mod
);
}
return
change
;
return
change
;
}
}
static
int
rsnd_dvc_pcm_new
(
struct
rsnd_mod
*
mod
,
static
int
__
rsnd_dvc_pcm_new
(
struct
rsnd_mod
*
mod
,
struct
rsnd_dai
*
rdai
,
struct
rsnd_dai
*
rdai
,
struct
snd_soc_pcm_runtime
*
rtd
)
struct
snd_soc_pcm_runtime
*
rtd
,
const
unsigned
char
*
name
,
u8
*
private
)
{
{
struct
rsnd_dai_stream
*
io
=
rsnd_mod_to_io
(
mod
);
struct
rsnd_priv
*
priv
=
rsnd_mod_to_priv
(
mod
);
struct
device
*
dev
=
rsnd_priv_to_dev
(
priv
);
struct
snd_card
*
card
=
rtd
->
card
->
snd_card
;
struct
snd_card
*
card
=
rtd
->
card
->
snd_card
;
struct
snd_kcontrol
*
kctrl
;
struct
snd_kcontrol
*
kctrl
;
st
atic
st
ruct
snd_kcontrol_new
knew
=
{
struct
snd_kcontrol_new
knew
=
{
.
iface
=
SNDRV_CTL_ELEM_IFACE_MIXER
,
.
iface
=
SNDRV_CTL_ELEM_IFACE_MIXER
,
.
name
=
"Playback Volume"
,
.
name
=
name
,
.
info
=
rsnd_dvc_volume_info
,
.
info
=
rsnd_dvc_volume_info
,
.
get
=
rsnd_dvc_volume_get
,
.
get
=
rsnd_dvc_volume_get
,
.
put
=
rsnd_dvc_volume_put
,
.
put
=
rsnd_dvc_volume_put
,
.
private_value
=
(
unsigned
long
)
private
,
};
};
int
ret
;
int
ret
;
if
(
!
rsnd_dai_is_play
(
rdai
,
io
))
{
dev_err
(
dev
,
"DVC%d is connected to Capture DAI
\n
"
,
rsnd_mod_id
(
mod
));
return
-
EINVAL
;
}
kctrl
=
snd_ctl_new1
(
&
knew
,
mod
);
kctrl
=
snd_ctl_new1
(
&
knew
,
mod
);
if
(
!
kctrl
)
if
(
!
kctrl
)
return
-
ENOMEM
;
return
-
ENOMEM
;
...
@@ -221,6 +223,33 @@ static int rsnd_dvc_pcm_new(struct rsnd_mod *mod,
...
@@ -221,6 +223,33 @@ static int rsnd_dvc_pcm_new(struct rsnd_mod *mod,
return
0
;
return
0
;
}
}
static
int
rsnd_dvc_pcm_new
(
struct
rsnd_mod
*
mod
,
struct
rsnd_dai
*
rdai
,
struct
snd_soc_pcm_runtime
*
rtd
)
{
struct
rsnd_dai_stream
*
io
=
rsnd_mod_to_io
(
mod
);
struct
rsnd_dvc
*
dvc
=
rsnd_mod_to_dvc
(
mod
);
int
ret
;
/* Volume */
ret
=
__rsnd_dvc_pcm_new
(
mod
,
rdai
,
rtd
,
rsnd_dai_is_play
(
rdai
,
io
)
?
"DVC Out Playback Volume"
:
"DVC In Capture Volume"
,
dvc
->
volume
);
if
(
ret
<
0
)
return
ret
;
/* Mute */
ret
=
__rsnd_dvc_pcm_new
(
mod
,
rdai
,
rtd
,
rsnd_dai_is_play
(
rdai
,
io
)
?
"DVC Out Mute Switch"
:
"DVC In Mute Switch"
,
dvc
->
mute
);
if
(
ret
<
0
)
return
ret
;
return
0
;
}
static
struct
rsnd_mod_ops
rsnd_dvc_ops
=
{
static
struct
rsnd_mod_ops
rsnd_dvc_ops
=
{
.
name
=
DVC_NAME
,
.
name
=
DVC_NAME
,
.
probe
=
rsnd_dvc_probe_gen2
,
.
probe
=
rsnd_dvc_probe_gen2
,
...
@@ -239,6 +268,42 @@ struct rsnd_mod *rsnd_dvc_mod_get(struct rsnd_priv *priv, int id)
...
@@ -239,6 +268,42 @@ struct rsnd_mod *rsnd_dvc_mod_get(struct rsnd_priv *priv, int id)
return
&
((
struct
rsnd_dvc
*
)(
priv
->
dvc
)
+
id
)
->
mod
;
return
&
((
struct
rsnd_dvc
*
)(
priv
->
dvc
)
+
id
)
->
mod
;
}
}
static
void
rsnd_of_parse_dvc
(
struct
platform_device
*
pdev
,
const
struct
rsnd_of_data
*
of_data
,
struct
rsnd_priv
*
priv
)
{
struct
device_node
*
node
;
struct
rsnd_dvc_platform_info
*
dvc_info
;
struct
rcar_snd_info
*
info
=
rsnd_priv_to_info
(
priv
);
struct
device
*
dev
=
&
pdev
->
dev
;
int
nr
;
if
(
!
of_data
)
return
;
node
=
of_get_child_by_name
(
dev
->
of_node
,
"rcar_sound,dvc"
);
if
(
!
node
)
return
;
nr
=
of_get_child_count
(
node
);
if
(
!
nr
)
goto
rsnd_of_parse_dvc_end
;
dvc_info
=
devm_kzalloc
(
dev
,
sizeof
(
struct
rsnd_dvc_platform_info
)
*
nr
,
GFP_KERNEL
);
if
(
!
dvc_info
)
{
dev_err
(
dev
,
"dvc info allocation error
\n
"
);
goto
rsnd_of_parse_dvc_end
;
}
info
->
dvc_info
=
dvc_info
;
info
->
dvc_info_nr
=
nr
;
rsnd_of_parse_dvc_end:
of_node_put
(
node
);
}
int
rsnd_dvc_probe
(
struct
platform_device
*
pdev
,
int
rsnd_dvc_probe
(
struct
platform_device
*
pdev
,
const
struct
rsnd_of_data
*
of_data
,
const
struct
rsnd_of_data
*
of_data
,
struct
rsnd_priv
*
priv
)
struct
rsnd_priv
*
priv
)
...
@@ -250,6 +315,8 @@ int rsnd_dvc_probe(struct platform_device *pdev,
...
@@ -250,6 +315,8 @@ int rsnd_dvc_probe(struct platform_device *pdev,
char
name
[
RSND_DVC_NAME_SIZE
];
char
name
[
RSND_DVC_NAME_SIZE
];
int
i
,
nr
;
int
i
,
nr
;
rsnd_of_parse_dvc
(
pdev
,
of_data
,
priv
);
nr
=
info
->
dvc_info_nr
;
nr
=
info
->
dvc_info_nr
;
if
(
!
nr
)
if
(
!
nr
)
return
0
;
return
0
;
...
...
sound/soc/sh/rcar/gen.c
浏览文件 @
2fd53734
...
@@ -15,63 +15,35 @@ struct rsnd_gen {
...
@@ -15,63 +15,35 @@ struct rsnd_gen {
struct
rsnd_gen_ops
*
ops
;
struct
rsnd_gen_ops
*
ops
;
struct
regmap
*
regmap
;
struct
regmap
*
regmap
[
RSND_BASE_MAX
]
;
struct
regmap_field
*
regs
[
RSND_REG_MAX
];
struct
regmap_field
*
regs
[
RSND_REG_MAX
];
};
};
#define rsnd_priv_to_gen(p) ((struct rsnd_gen *)(p)->gen)
#define rsnd_priv_to_gen(p) ((struct rsnd_gen *)(p)->gen)
#define RSND_REG_SET(gen, id, reg_id, offset, _id_offset, _id_size) \
struct
rsnd_regmap_field_conf
{
[id] = { \
int
idx
;
.reg = (unsigned int)gen->base[reg_id] + offset, \
unsigned
int
reg_offset
;
.lsb = 0, \
unsigned
int
id_offset
;
.msb = 31, \
};
.id_size = _id_size, \
#define RSND_REG_SET(id, offset, _id_offset) \
{ \
.idx = id, \
.reg_offset = offset, \
.id_offset = _id_offset, \
.id_offset = _id_offset, \
}
}
/* single address mapping */
#define RSND_GEN_S_REG(id, offset) \
RSND_REG_SET(RSND_REG_##id, offset, 0)
/* multi address mapping */
#define RSND_GEN_M_REG(id, offset, _id_offset) \
RSND_REG_SET(RSND_REG_##id, offset, _id_offset)
/*
/*
* basic function
* basic function
*/
*/
static
int
rsnd_regmap_write32
(
void
*
context
,
const
void
*
_data
,
size_t
count
)
{
struct
rsnd_priv
*
priv
=
context
;
struct
device
*
dev
=
rsnd_priv_to_dev
(
priv
);
u32
*
data
=
(
u32
*
)
_data
;
u32
val
=
data
[
1
];
void
__iomem
*
reg
=
(
void
*
)
data
[
0
];
iowrite32
(
val
,
reg
);
dev_dbg
(
dev
,
"w %p : %08x
\n
"
,
reg
,
val
);
return
0
;
}
static
int
rsnd_regmap_read32
(
void
*
context
,
const
void
*
_data
,
size_t
reg_size
,
void
*
_val
,
size_t
val_size
)
{
struct
rsnd_priv
*
priv
=
context
;
struct
device
*
dev
=
rsnd_priv_to_dev
(
priv
);
u32
*
data
=
(
u32
*
)
_data
;
u32
*
val
=
(
u32
*
)
_val
;
void
__iomem
*
reg
=
(
void
*
)
data
[
0
];
*
val
=
ioread32
(
reg
);
dev_dbg
(
dev
,
"r %p : %08x
\n
"
,
reg
,
*
val
);
return
0
;
}
static
struct
regmap_bus
rsnd_regmap_bus
=
{
.
write
=
rsnd_regmap_write32
,
.
read
=
rsnd_regmap_read32
,
.
reg_format_endian_default
=
REGMAP_ENDIAN_NATIVE
,
.
val_format_endian_default
=
REGMAP_ENDIAN_NATIVE
,
};
static
int
rsnd_is_accessible_reg
(
struct
rsnd_priv
*
priv
,
static
int
rsnd_is_accessible_reg
(
struct
rsnd_priv
*
priv
,
struct
rsnd_gen
*
gen
,
enum
rsnd_reg
reg
)
struct
rsnd_gen
*
gen
,
enum
rsnd_reg
reg
)
{
{
...
@@ -88,6 +60,7 @@ static int rsnd_is_accessible_reg(struct rsnd_priv *priv,
...
@@ -88,6 +60,7 @@ static int rsnd_is_accessible_reg(struct rsnd_priv *priv,
u32
rsnd_read
(
struct
rsnd_priv
*
priv
,
u32
rsnd_read
(
struct
rsnd_priv
*
priv
,
struct
rsnd_mod
*
mod
,
enum
rsnd_reg
reg
)
struct
rsnd_mod
*
mod
,
enum
rsnd_reg
reg
)
{
{
struct
device
*
dev
=
rsnd_priv_to_dev
(
priv
);
struct
rsnd_gen
*
gen
=
rsnd_priv_to_gen
(
priv
);
struct
rsnd_gen
*
gen
=
rsnd_priv_to_gen
(
priv
);
u32
val
;
u32
val
;
...
@@ -96,6 +69,8 @@ u32 rsnd_read(struct rsnd_priv *priv,
...
@@ -96,6 +69,8 @@ u32 rsnd_read(struct rsnd_priv *priv,
regmap_fields_read
(
gen
->
regs
[
reg
],
rsnd_mod_id
(
mod
),
&
val
);
regmap_fields_read
(
gen
->
regs
[
reg
],
rsnd_mod_id
(
mod
),
&
val
);
dev_dbg
(
dev
,
"r %s - 0x%04d : %08x
\n
"
,
rsnd_mod_name
(
mod
),
reg
,
val
);
return
val
;
return
val
;
}
}
...
@@ -103,17 +78,21 @@ void rsnd_write(struct rsnd_priv *priv,
...
@@ -103,17 +78,21 @@ void rsnd_write(struct rsnd_priv *priv,
struct
rsnd_mod
*
mod
,
struct
rsnd_mod
*
mod
,
enum
rsnd_reg
reg
,
u32
data
)
enum
rsnd_reg
reg
,
u32
data
)
{
{
struct
device
*
dev
=
rsnd_priv_to_dev
(
priv
);
struct
rsnd_gen
*
gen
=
rsnd_priv_to_gen
(
priv
);
struct
rsnd_gen
*
gen
=
rsnd_priv_to_gen
(
priv
);
if
(
!
rsnd_is_accessible_reg
(
priv
,
gen
,
reg
))
if
(
!
rsnd_is_accessible_reg
(
priv
,
gen
,
reg
))
return
;
return
;
regmap_fields_write
(
gen
->
regs
[
reg
],
rsnd_mod_id
(
mod
),
data
);
regmap_fields_write
(
gen
->
regs
[
reg
],
rsnd_mod_id
(
mod
),
data
);
dev_dbg
(
dev
,
"w %s - 0x%04d : %08x
\n
"
,
rsnd_mod_name
(
mod
),
reg
,
data
);
}
}
void
rsnd_bset
(
struct
rsnd_priv
*
priv
,
struct
rsnd_mod
*
mod
,
void
rsnd_bset
(
struct
rsnd_priv
*
priv
,
struct
rsnd_mod
*
mod
,
enum
rsnd_reg
reg
,
u32
mask
,
u32
data
)
enum
rsnd_reg
reg
,
u32
mask
,
u32
data
)
{
{
struct
device
*
dev
=
rsnd_priv_to_dev
(
priv
);
struct
rsnd_gen
*
gen
=
rsnd_priv_to_gen
(
priv
);
struct
rsnd_gen
*
gen
=
rsnd_priv_to_gen
(
priv
);
if
(
!
rsnd_is_accessible_reg
(
priv
,
gen
,
reg
))
if
(
!
rsnd_is_accessible_reg
(
priv
,
gen
,
reg
))
...
@@ -121,35 +100,63 @@ void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod,
...
@@ -121,35 +100,63 @@ void rsnd_bset(struct rsnd_priv *priv, struct rsnd_mod *mod,
regmap_fields_update_bits
(
gen
->
regs
[
reg
],
rsnd_mod_id
(
mod
),
regmap_fields_update_bits
(
gen
->
regs
[
reg
],
rsnd_mod_id
(
mod
),
mask
,
data
);
mask
,
data
);
dev_dbg
(
dev
,
"b %s - 0x%04d : %08x/%08x
\n
"
,
rsnd_mod_name
(
mod
),
reg
,
data
,
mask
);
}
}
static
int
rsnd_gen_regmap_init
(
struct
rsnd_priv
*
priv
,
#define rsnd_gen_regmap_init(priv, id_size, reg_id, conf) \
struct
rsnd_gen
*
gen
,
_rsnd_gen_regmap_init(priv, id_size, reg_id, conf, ARRAY_SIZE(conf))
struct
reg_field
*
regf
)
static
int
_rsnd_gen_regmap_init
(
struct
rsnd_priv
*
priv
,
int
id_size
,
int
reg_id
,
struct
rsnd_regmap_field_conf
*
conf
,
int
conf_size
)
{
{
int
i
;
struct
platform_device
*
pdev
=
rsnd_priv_to_pdev
(
priv
);
struct
rsnd_gen
*
gen
=
rsnd_priv_to_gen
(
priv
);
struct
device
*
dev
=
rsnd_priv_to_dev
(
priv
);
struct
device
*
dev
=
rsnd_priv_to_dev
(
priv
);
struct
resource
*
res
;
struct
regmap_config
regc
;
struct
regmap_config
regc
;
struct
regmap_field
*
regs
;
struct
regmap
*
regmap
;
struct
reg_field
regf
;
void
__iomem
*
base
;
int
i
;
memset
(
&
regc
,
0
,
sizeof
(
regc
));
memset
(
&
regc
,
0
,
sizeof
(
regc
));
regc
.
reg_bits
=
32
;
regc
.
reg_bits
=
32
;
regc
.
val_bits
=
32
;
regc
.
val_bits
=
32
;
regc
.
reg_stride
=
4
;
gen
->
regmap
=
devm_regmap_init
(
dev
,
&
rsnd_regmap_bus
,
priv
,
&
regc
);
res
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
reg_id
);
if
(
IS_ERR
(
gen
->
regmap
))
{
if
(
!
res
)
dev_err
(
dev
,
"regmap error %ld
\n
"
,
PTR_ERR
(
gen
->
regmap
));
return
-
ENODEV
;
return
PTR_ERR
(
gen
->
regmap
);
}
for
(
i
=
0
;
i
<
RSND_REG_MAX
;
i
++
)
{
base
=
devm_ioremap_resource
(
dev
,
res
);
gen
->
regs
[
i
]
=
NULL
;
if
(
IS_ERR
(
base
))
if
(
!
regf
[
i
].
reg
)
return
PTR_ERR
(
base
);
continue
;
gen
->
regs
[
i
]
=
devm_regmap_field_alloc
(
dev
,
gen
->
regmap
,
regf
[
i
]
);
regmap
=
devm_regmap_init_mmio
(
dev
,
base
,
&
regc
);
if
(
IS_ERR
(
gen
->
regs
[
i
]
))
if
(
IS_ERR
(
regmap
))
return
PTR_ERR
(
gen
->
regs
[
i
]
);
return
PTR_ERR
(
regmap
);
gen
->
base
[
reg_id
]
=
base
;
gen
->
regmap
[
reg_id
]
=
regmap
;
for
(
i
=
0
;
i
<
conf_size
;
i
++
)
{
regf
.
reg
=
conf
[
i
].
reg_offset
;
regf
.
id_offset
=
conf
[
i
].
id_offset
;
regf
.
lsb
=
0
;
regf
.
msb
=
31
;
regf
.
id_size
=
id_size
;
regs
=
devm_regmap_field_alloc
(
dev
,
regmap
,
regf
);
if
(
IS_ERR
(
regs
))
return
PTR_ERR
(
regs
);
gen
->
regs
[
conf
[
i
].
idx
]
=
regs
;
}
}
return
0
;
return
0
;
...
@@ -165,15 +172,19 @@ static int rsnd_gen_regmap_init(struct rsnd_priv *priv,
...
@@ -165,15 +172,19 @@ static int rsnd_gen_regmap_init(struct rsnd_priv *priv,
*
*
* ex) R-Car H2 case
* ex) R-Car H2 case
* mod / DMAC in / DMAC out / DMAC PP in / DMAC pp out
* mod / DMAC in / DMAC out / DMAC PP in / DMAC pp out
* SSI : 0xec541000 / 0xec241008 / 0xec24100c / 0xec400000 / 0xec400000
* SSI : 0xec541000 / 0xec241008 / 0xec24100c
* SSIU: 0xec541000 / 0xec100000 / 0xec100000 / 0xec400000 / 0xec400000
* SCU : 0xec500000 / 0xec000000 / 0xec004000 / 0xec300000 / 0xec304000
* SCU : 0xec500000 / 0xec000000 / 0xec004000 / 0xec300000 / 0xec304000
* CMD : 0xec500000 /
0xec008000
0xec308000
* CMD : 0xec500000 /
/ 0xec008000
0xec308000
*/
*/
#define RDMA_SSI_I_N(addr, i) (addr ##_reg - 0x00300000 + (0x40 * i) + 0x8)
#define RDMA_SSI_I_N(addr, i) (addr ##_reg - 0x00300000 + (0x40 * i) + 0x8)
#define RDMA_SSI_O_N(addr, i) (addr ##_reg - 0x00300000 + (0x40 * i) + 0xc)
#define RDMA_SSI_O_N(addr, i) (addr ##_reg - 0x00300000 + (0x40 * i) + 0xc)
#define RDMA_SSI_I_P(addr, i) (addr ##_reg - 0x00141000 + (0x1000 * i))
#define RDMA_SSIU_I_N(addr, i) (addr ##_reg - 0x00441000 + (0x1000 * i))
#define RDMA_SSI_O_P(addr, i) (addr ##_reg - 0x00141000 + (0x1000 * i))
#define RDMA_SSIU_O_N(addr, i) (addr ##_reg - 0x00441000 + (0x1000 * i))
#define RDMA_SSIU_I_P(addr, i) (addr ##_reg - 0x00141000 + (0x1000 * i))
#define RDMA_SSIU_O_P(addr, i) (addr ##_reg - 0x00141000 + (0x1000 * i))
#define RDMA_SRC_I_N(addr, i) (addr ##_reg - 0x00500000 + (0x400 * i))
#define RDMA_SRC_I_N(addr, i) (addr ##_reg - 0x00500000 + (0x400 * i))
#define RDMA_SRC_O_N(addr, i) (addr ##_reg - 0x004fc000 + (0x400 * i))
#define RDMA_SRC_O_N(addr, i) (addr ##_reg - 0x004fc000 + (0x400 * i))
...
@@ -184,14 +195,13 @@ static int rsnd_gen_regmap_init(struct rsnd_priv *priv,
...
@@ -184,14 +195,13 @@ static int rsnd_gen_regmap_init(struct rsnd_priv *priv,
#define RDMA_CMD_O_N(addr, i) (addr ##_reg - 0x004f8000 + (0x400 * i))
#define RDMA_CMD_O_N(addr, i) (addr ##_reg - 0x004f8000 + (0x400 * i))
#define RDMA_CMD_O_P(addr, i) (addr ##_reg - 0x001f8000 + (0x400 * i))
#define RDMA_CMD_O_P(addr, i) (addr ##_reg - 0x001f8000 + (0x400 * i))
static
void
rsnd_gen2_dma_addr
(
struct
rsnd_priv
*
priv
,
static
dma_addr_t
struct
rsnd_dma
*
dma
,
rsnd_gen2_dma_addr
(
struct
rsnd_priv
*
priv
,
struct
dma_slave_config
*
cfg
,
struct
rsnd_mod
*
mod
,
int
is_play
,
int
slave_id
)
int
is_play
,
int
is_from
)
{
{
struct
platform_device
*
pdev
=
rsnd_priv_to_pdev
(
priv
);
struct
platform_device
*
pdev
=
rsnd_priv_to_pdev
(
priv
);
struct
device
*
dev
=
rsnd_priv_to_dev
(
priv
);
struct
device
*
dev
=
rsnd_priv_to_dev
(
priv
);
struct
rsnd_mod
*
mod
=
rsnd_dma_to_mod
(
dma
);
struct
rsnd_dai_stream
*
io
=
rsnd_mod_to_io
(
mod
);
struct
rsnd_dai_stream
*
io
=
rsnd_mod_to_io
(
mod
);
dma_addr_t
ssi_reg
=
platform_get_resource
(
pdev
,
dma_addr_t
ssi_reg
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
RSND_GEN2_SSI
)
->
start
;
IORESOURCE_MEM
,
RSND_GEN2_SSI
)
->
start
;
...
@@ -202,179 +212,152 @@ static void rsnd_gen2_dma_addr(struct rsnd_priv *priv,
...
@@ -202,179 +212,152 @@ static void rsnd_gen2_dma_addr(struct rsnd_priv *priv,
int
use_dvc
=
!!
rsnd_io_to_mod_dvc
(
io
);
int
use_dvc
=
!!
rsnd_io_to_mod_dvc
(
io
);
int
id
=
rsnd_mod_id
(
mod
);
int
id
=
rsnd_mod_id
(
mod
);
struct
dma_addr
{
struct
dma_addr
{
dma_addr_t
src_addr
;
dma_addr_t
out_addr
;
dma_addr_t
dst_addr
;
dma_addr_t
in_addr
;
}
dma_addrs
[
2
][
2
][
3
]
=
{
}
dma_addrs
[
3
][
2
][
3
]
=
{
{
/* SRC */
/* SRC */
{{{
0
,
0
},
/* Capture */
/* Capture */
{{
0
,
0
},
{
RDMA_SRC_O_N
(
src
,
id
),
RDMA_SRC_I_P
(
src
,
id
)
},
{
RDMA_SRC_O_N
(
src
,
id
),
0
},
{
RDMA_CMD_O_N
(
src
,
id
),
RDMA_SRC_I_P
(
src
,
id
)
}
},
{
RDMA_CMD_O_N
(
src
,
id
),
0
}},
/* Playback */
/* Playback */
{{
0
,
0
,
},
{{
0
,
0
,
},
{
0
,
RDMA_SRC_I_N
(
src
,
id
)
},
{
RDMA_SRC_O_P
(
src
,
id
),
RDMA_SRC_I_N
(
src
,
id
)
},
{
0
,
RDMA_SRC_I_N
(
src
,
id
)
}}
{
RDMA_CMD_O_P
(
src
,
id
),
RDMA_SRC_I_N
(
src
,
id
)
}
}
},
{
/* SSI */
},
/* SSI */
/* Capture */
/* Capture */
{{
RDMA_SSI_O_N
(
ssi
,
id
),
0
},
{
{{
RDMA_SSI_O_N
(
ssi
,
id
),
0
},
{
RDMA_SSI_O_P
(
ssi
,
id
),
RDMA_SRC_I_P
(
src
,
id
)
},
{
RDMA_SSIU_O_P
(
ssi
,
id
),
0
},
{
RDMA_SSI_O_P
(
ssi
,
id
),
RDMA_SRC_I_P
(
src
,
id
)
}
},
{
RDMA_SSIU_O_P
(
ssi
,
id
),
0
}
},
/* Playback */
/* Playback */
{{
0
,
RDMA_SSI_I_N
(
ssi
,
id
)
},
{{
0
,
RDMA_SSI_I_N
(
ssi
,
id
)
},
{
RDMA_SRC_O_P
(
src
,
id
),
RDMA_SSI_I_P
(
ssi
,
id
)
},
{
0
,
RDMA_SSIU_I_P
(
ssi
,
id
)
},
{
RDMA_CMD_O_P
(
src
,
id
),
RDMA_SSI_I_P
(
ssi
,
id
)
}}
{
0
,
RDMA_SSIU_I_P
(
ssi
,
id
)
}
}
}
},
/* SSIU */
/* Capture */
{{{
RDMA_SSIU_O_N
(
ssi
,
id
),
0
},
{
RDMA_SSIU_O_P
(
ssi
,
id
),
0
},
{
RDMA_SSIU_O_P
(
ssi
,
id
),
0
}
},
/* Playback */
{{
0
,
RDMA_SSIU_I_N
(
ssi
,
id
)
},
{
0
,
RDMA_SSIU_I_P
(
ssi
,
id
)
},
{
0
,
RDMA_SSIU_I_P
(
ssi
,
id
)
}
}
},
};
};
/* it shouldn't happen */
/* it shouldn't happen */
if
(
use_dvc
&
!
use_src
)
{
if
(
use_dvc
&
!
use_src
)
dev_err
(
dev
,
"DVC is selected without SRC
\n
"
);
dev_err
(
dev
,
"DVC is selected without SRC
\n
"
);
return
;
}
cfg
->
src_addr
=
dma_addrs
[
is_ssi
][
is_play
][
use_src
+
use_dvc
].
src_addr
;
/* use SSIU or SSI ? */
cfg
->
dst_addr
=
dma_addrs
[
is_ssi
][
is_play
][
use_src
+
use_dvc
].
dst_addr
;
if
(
is_ssi
&&
(
0
==
strcmp
(
rsnd_mod_dma_name
(
mod
),
"ssiu"
)))
is_ssi
++
;
dev_dbg
(
dev
,
"dma%d addr - src : %x / dst : %x
\n
"
,
return
(
is_from
)
?
id
,
cfg
->
src_addr
,
cfg
->
dst_addr
);
dma_addrs
[
is_ssi
][
is_play
][
use_src
+
use_dvc
].
out_addr
:
dma_addrs
[
is_ssi
][
is_play
][
use_src
+
use_dvc
].
in_addr
;
}
}
void
rsnd_gen_dma_addr
(
struct
rsnd_priv
*
priv
,
dma_addr_t
rsnd_gen_dma_addr
(
struct
rsnd_priv
*
priv
,
struct
rsnd_dma
*
dma
,
struct
rsnd_mod
*
mod
,
struct
dma_slave_config
*
cfg
,
int
is_play
,
int
is_from
)
int
is_play
,
int
slave_id
)
{
{
cfg
->
slave_id
=
slave_id
;
cfg
->
src_addr
=
0
;
cfg
->
dst_addr
=
0
;
cfg
->
direction
=
is_play
?
DMA_MEM_TO_DEV
:
DMA_DEV_TO_MEM
;
/*
/*
* gen1 uses default DMA addr
* gen1 uses default DMA addr
*/
*/
if
(
rsnd_is_gen1
(
priv
))
if
(
rsnd_is_gen1
(
priv
))
return
;
return
0
;
rsnd_gen2_dma_addr
(
priv
,
dma
,
cfg
,
is_play
,
slave_id
);
if
(
!
mod
)
}
return
0
;
return
rsnd_gen2_dma_addr
(
priv
,
mod
,
is_play
,
is_from
);
}
/*
/*
* Gen2
* Gen2
*/
*/
/* single address mapping */
#define RSND_GEN2_S_REG(gen, reg, id, offset) \
RSND_REG_SET(gen, RSND_REG_##id, RSND_GEN2_##reg, offset, 0, 10)
/* multi address mapping */
#define RSND_GEN2_M_REG(gen, reg, id, offset, _id_offset) \
RSND_REG_SET(gen, RSND_REG_##id, RSND_GEN2_##reg, offset, _id_offset, 10)
static
int
rsnd_gen2_regmap_init
(
struct
rsnd_priv
*
priv
,
struct
rsnd_gen
*
gen
)
{
struct
reg_field
regf
[
RSND_REG_MAX
]
=
{
RSND_GEN2_S_REG
(
gen
,
SSIU
,
SSI_MODE0
,
0x800
),
RSND_GEN2_S_REG
(
gen
,
SSIU
,
SSI_MODE1
,
0x804
),
/* FIXME: it needs SSI_MODE2/3 in the future */
RSND_GEN2_M_REG
(
gen
,
SSIU
,
SSI_BUSIF_MODE
,
0x0
,
0x80
),
RSND_GEN2_M_REG
(
gen
,
SSIU
,
SSI_BUSIF_ADINR
,
0x4
,
0x80
),
RSND_GEN2_M_REG
(
gen
,
SSIU
,
SSI_CTRL
,
0x10
,
0x80
),
RSND_GEN2_M_REG
(
gen
,
SSIU
,
INT_ENABLE
,
0x18
,
0x80
),
RSND_GEN2_M_REG
(
gen
,
SCU
,
SRC_BUSIF_MODE
,
0x0
,
0x20
),
RSND_GEN2_M_REG
(
gen
,
SCU
,
SRC_ROUTE_MODE0
,
0xc
,
0x20
),
RSND_GEN2_M_REG
(
gen
,
SCU
,
SRC_CTRL
,
0x10
,
0x20
),
RSND_GEN2_M_REG
(
gen
,
SCU
,
CMD_ROUTE_SLCT
,
0x18c
,
0x20
),
RSND_GEN2_M_REG
(
gen
,
SCU
,
CMD_CTRL
,
0x190
,
0x20
),
RSND_GEN2_M_REG
(
gen
,
SCU
,
SRC_SWRSR
,
0x200
,
0x40
),
RSND_GEN2_M_REG
(
gen
,
SCU
,
SRC_SRCIR
,
0x204
,
0x40
),
RSND_GEN2_M_REG
(
gen
,
SCU
,
SRC_ADINR
,
0x214
,
0x40
),
RSND_GEN2_M_REG
(
gen
,
SCU
,
SRC_IFSCR
,
0x21c
,
0x40
),
RSND_GEN2_M_REG
(
gen
,
SCU
,
SRC_IFSVR
,
0x220
,
0x40
),
RSND_GEN2_M_REG
(
gen
,
SCU
,
SRC_SRCCR
,
0x224
,
0x40
),
RSND_GEN2_M_REG
(
gen
,
SCU
,
SRC_BSDSR
,
0x22c
,
0x40
),
RSND_GEN2_M_REG
(
gen
,
SCU
,
SRC_BSISR
,
0x238
,
0x40
),
RSND_GEN2_M_REG
(
gen
,
SCU
,
DVC_SWRSR
,
0xe00
,
0x100
),
RSND_GEN2_M_REG
(
gen
,
SCU
,
DVC_DVUIR
,
0xe04
,
0x100
),
RSND_GEN2_M_REG
(
gen
,
SCU
,
DVC_ADINR
,
0xe08
,
0x100
),
RSND_GEN2_M_REG
(
gen
,
SCU
,
DVC_DVUCR
,
0xe10
,
0x100
),
RSND_GEN2_M_REG
(
gen
,
SCU
,
DVC_ZCMCR
,
0xe14
,
0x100
),
RSND_GEN2_M_REG
(
gen
,
SCU
,
DVC_VOL0R
,
0xe28
,
0x100
),
RSND_GEN2_M_REG
(
gen
,
SCU
,
DVC_VOL1R
,
0xe2c
,
0x100
),
RSND_GEN2_M_REG
(
gen
,
SCU
,
DVC_DVUER
,
0xe48
,
0x100
),
RSND_GEN2_S_REG
(
gen
,
ADG
,
BRRA
,
0x00
),
RSND_GEN2_S_REG
(
gen
,
ADG
,
BRRB
,
0x04
),
RSND_GEN2_S_REG
(
gen
,
ADG
,
SSICKR
,
0x08
),
RSND_GEN2_S_REG
(
gen
,
ADG
,
AUDIO_CLK_SEL0
,
0x0c
),
RSND_GEN2_S_REG
(
gen
,
ADG
,
AUDIO_CLK_SEL1
,
0x10
),
RSND_GEN2_S_REG
(
gen
,
ADG
,
AUDIO_CLK_SEL2
,
0x14
),
RSND_GEN2_S_REG
(
gen
,
ADG
,
DIV_EN
,
0x30
),
RSND_GEN2_S_REG
(
gen
,
ADG
,
SRCIN_TIMSEL0
,
0x34
),
RSND_GEN2_S_REG
(
gen
,
ADG
,
SRCIN_TIMSEL1
,
0x38
),
RSND_GEN2_S_REG
(
gen
,
ADG
,
SRCIN_TIMSEL2
,
0x3c
),
RSND_GEN2_S_REG
(
gen
,
ADG
,
SRCIN_TIMSEL3
,
0x40
),
RSND_GEN2_S_REG
(
gen
,
ADG
,
SRCIN_TIMSEL4
,
0x44
),
RSND_GEN2_S_REG
(
gen
,
ADG
,
SRCOUT_TIMSEL0
,
0x48
),
RSND_GEN2_S_REG
(
gen
,
ADG
,
SRCOUT_TIMSEL1
,
0x4c
),
RSND_GEN2_S_REG
(
gen
,
ADG
,
SRCOUT_TIMSEL2
,
0x50
),
RSND_GEN2_S_REG
(
gen
,
ADG
,
SRCOUT_TIMSEL3
,
0x54
),
RSND_GEN2_S_REG
(
gen
,
ADG
,
SRCOUT_TIMSEL4
,
0x58
),
RSND_GEN2_S_REG
(
gen
,
ADG
,
CMDOUT_TIMSEL
,
0x5c
),
RSND_GEN2_M_REG
(
gen
,
SSI
,
SSICR
,
0x00
,
0x40
),
RSND_GEN2_M_REG
(
gen
,
SSI
,
SSISR
,
0x04
,
0x40
),
RSND_GEN2_M_REG
(
gen
,
SSI
,
SSITDR
,
0x08
,
0x40
),
RSND_GEN2_M_REG
(
gen
,
SSI
,
SSIRDR
,
0x0c
,
0x40
),
RSND_GEN2_M_REG
(
gen
,
SSI
,
SSIWSR
,
0x20
,
0x40
),
};
return
rsnd_gen_regmap_init
(
priv
,
gen
,
regf
);
}
static
int
rsnd_gen2_probe
(
struct
platform_device
*
pdev
,
static
int
rsnd_gen2_probe
(
struct
platform_device
*
pdev
,
struct
rsnd_priv
*
priv
)
struct
rsnd_priv
*
priv
)
{
{
struct
device
*
dev
=
rsnd_priv_to_dev
(
priv
);
struct
device
*
dev
=
rsnd_priv_to_dev
(
priv
);
struct
rsnd_gen
*
gen
=
rsnd_priv_to_gen
(
priv
);
struct
rsnd_regmap_field_conf
conf_ssiu
[]
=
{
struct
resource
*
scu_res
;
RSND_GEN_S_REG
(
SSI_MODE0
,
0x800
),
struct
resource
*
adg_res
;
RSND_GEN_S_REG
(
SSI_MODE1
,
0x804
),
struct
resource
*
ssiu_res
;
/* FIXME: it needs SSI_MODE2/3 in the future */
struct
resource
*
ssi_res
;
RSND_GEN_M_REG
(
SSI_BUSIF_MODE
,
0x0
,
0x80
),
int
ret
;
RSND_GEN_M_REG
(
SSI_BUSIF_ADINR
,
0x4
,
0x80
),
RSND_GEN_M_REG
(
BUSIF_DALIGN
,
0x8
,
0x80
),
/*
RSND_GEN_M_REG
(
SSI_CTRL
,
0x10
,
0x80
),
* map address
RSND_GEN_M_REG
(
INT_ENABLE
,
0x18
,
0x80
),
*/
};
scu_res
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
RSND_GEN2_SCU
);
struct
rsnd_regmap_field_conf
conf_scu
[]
=
{
adg_res
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
RSND_GEN2_ADG
);
RSND_GEN_M_REG
(
SRC_BUSIF_MODE
,
0x0
,
0x20
),
ssiu_res
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
RSND_GEN2_SSIU
);
RSND_GEN_M_REG
(
SRC_ROUTE_MODE0
,
0xc
,
0x20
),
ssi_res
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
RSND_GEN2_SSI
);
RSND_GEN_M_REG
(
SRC_CTRL
,
0x10
,
0x20
),
RSND_GEN_M_REG
(
CMD_ROUTE_SLCT
,
0x18c
,
0x20
),
gen
->
base
[
RSND_GEN2_SCU
]
=
devm_ioremap_resource
(
dev
,
scu_res
);
RSND_GEN_M_REG
(
CMD_CTRL
,
0x190
,
0x20
),
gen
->
base
[
RSND_GEN2_ADG
]
=
devm_ioremap_resource
(
dev
,
adg_res
);
RSND_GEN_M_REG
(
SRC_SWRSR
,
0x200
,
0x40
),
gen
->
base
[
RSND_GEN2_SSIU
]
=
devm_ioremap_resource
(
dev
,
ssiu_res
);
RSND_GEN_M_REG
(
SRC_SRCIR
,
0x204
,
0x40
),
gen
->
base
[
RSND_GEN2_SSI
]
=
devm_ioremap_resource
(
dev
,
ssi_res
);
RSND_GEN_M_REG
(
SRC_ADINR
,
0x214
,
0x40
),
if
(
IS_ERR
(
gen
->
base
[
RSND_GEN2_SCU
])
||
RSND_GEN_M_REG
(
SRC_IFSCR
,
0x21c
,
0x40
),
IS_ERR
(
gen
->
base
[
RSND_GEN2_ADG
])
||
RSND_GEN_M_REG
(
SRC_IFSVR
,
0x220
,
0x40
),
IS_ERR
(
gen
->
base
[
RSND_GEN2_SSIU
])
||
RSND_GEN_M_REG
(
SRC_SRCCR
,
0x224
,
0x40
),
IS_ERR
(
gen
->
base
[
RSND_GEN2_SSI
]))
RSND_GEN_M_REG
(
SRC_BSDSR
,
0x22c
,
0x40
),
return
-
ENODEV
;
RSND_GEN_M_REG
(
SRC_BSISR
,
0x238
,
0x40
),
RSND_GEN_M_REG
(
DVC_SWRSR
,
0xe00
,
0x100
),
ret
=
rsnd_gen2_regmap_init
(
priv
,
gen
);
RSND_GEN_M_REG
(
DVC_DVUIR
,
0xe04
,
0x100
),
if
(
ret
<
0
)
RSND_GEN_M_REG
(
DVC_ADINR
,
0xe08
,
0x100
),
return
ret
;
RSND_GEN_M_REG
(
DVC_DVUCR
,
0xe10
,
0x100
),
RSND_GEN_M_REG
(
DVC_ZCMCR
,
0xe14
,
0x100
),
dev_dbg
(
dev
,
"Gen2 device probed
\n
"
);
RSND_GEN_M_REG
(
DVC_VOL0R
,
0xe28
,
0x100
),
dev_dbg
(
dev
,
"SCU : %pap => %p
\n
"
,
&
scu_res
->
start
,
RSND_GEN_M_REG
(
DVC_VOL1R
,
0xe2c
,
0x100
),
gen
->
base
[
RSND_GEN2_SCU
]);
RSND_GEN_M_REG
(
DVC_DVUER
,
0xe48
,
0x100
),
dev_dbg
(
dev
,
"ADG : %pap => %p
\n
"
,
&
adg_res
->
start
,
};
gen
->
base
[
RSND_GEN2_ADG
]);
struct
rsnd_regmap_field_conf
conf_adg
[]
=
{
dev_dbg
(
dev
,
"SSIU : %pap => %p
\n
"
,
&
ssiu_res
->
start
,
RSND_GEN_S_REG
(
BRRA
,
0x00
),
gen
->
base
[
RSND_GEN2_SSIU
]);
RSND_GEN_S_REG
(
BRRB
,
0x04
),
dev_dbg
(
dev
,
"SSI : %pap => %p
\n
"
,
&
ssi_res
->
start
,
RSND_GEN_S_REG
(
SSICKR
,
0x08
),
gen
->
base
[
RSND_GEN2_SSI
]);
RSND_GEN_S_REG
(
AUDIO_CLK_SEL0
,
0x0c
),
RSND_GEN_S_REG
(
AUDIO_CLK_SEL1
,
0x10
),
RSND_GEN_S_REG
(
AUDIO_CLK_SEL2
,
0x14
),
RSND_GEN_S_REG
(
DIV_EN
,
0x30
),
RSND_GEN_S_REG
(
SRCIN_TIMSEL0
,
0x34
),
RSND_GEN_S_REG
(
SRCIN_TIMSEL1
,
0x38
),
RSND_GEN_S_REG
(
SRCIN_TIMSEL2
,
0x3c
),
RSND_GEN_S_REG
(
SRCIN_TIMSEL3
,
0x40
),
RSND_GEN_S_REG
(
SRCIN_TIMSEL4
,
0x44
),
RSND_GEN_S_REG
(
SRCOUT_TIMSEL0
,
0x48
),
RSND_GEN_S_REG
(
SRCOUT_TIMSEL1
,
0x4c
),
RSND_GEN_S_REG
(
SRCOUT_TIMSEL2
,
0x50
),
RSND_GEN_S_REG
(
SRCOUT_TIMSEL3
,
0x54
),
RSND_GEN_S_REG
(
SRCOUT_TIMSEL4
,
0x58
),
RSND_GEN_S_REG
(
CMDOUT_TIMSEL
,
0x5c
),
};
struct
rsnd_regmap_field_conf
conf_ssi
[]
=
{
RSND_GEN_M_REG
(
SSICR
,
0x00
,
0x40
),
RSND_GEN_M_REG
(
SSISR
,
0x04
,
0x40
),
RSND_GEN_M_REG
(
SSITDR
,
0x08
,
0x40
),
RSND_GEN_M_REG
(
SSIRDR
,
0x0c
,
0x40
),
RSND_GEN_M_REG
(
SSIWSR
,
0x20
,
0x40
),
};
int
ret_ssiu
;
int
ret_scu
;
int
ret_adg
;
int
ret_ssi
;
ret_ssiu
=
rsnd_gen_regmap_init
(
priv
,
10
,
RSND_GEN2_SSIU
,
conf_ssiu
);
ret_scu
=
rsnd_gen_regmap_init
(
priv
,
10
,
RSND_GEN2_SCU
,
conf_scu
);
ret_adg
=
rsnd_gen_regmap_init
(
priv
,
10
,
RSND_GEN2_ADG
,
conf_adg
);
ret_ssi
=
rsnd_gen_regmap_init
(
priv
,
10
,
RSND_GEN2_SSI
,
conf_ssi
);
if
(
ret_ssiu
<
0
||
ret_scu
<
0
||
ret_adg
<
0
||
ret_ssi
<
0
)
return
ret_ssiu
|
ret_scu
|
ret_adg
|
ret_ssi
;
dev_dbg
(
dev
,
"Gen2 is probed
\n
"
);
return
0
;
return
0
;
}
}
...
@@ -383,92 +366,60 @@ static int rsnd_gen2_probe(struct platform_device *pdev,
...
@@ -383,92 +366,60 @@ static int rsnd_gen2_probe(struct platform_device *pdev,
* Gen1
* Gen1
*/
*/
/* single address mapping */
#define RSND_GEN1_S_REG(gen, reg, id, offset) \
RSND_REG_SET(gen, RSND_REG_##id, RSND_GEN1_##reg, offset, 0, 9)
/* multi address mapping */
#define RSND_GEN1_M_REG(gen, reg, id, offset, _id_offset) \
RSND_REG_SET(gen, RSND_REG_##id, RSND_GEN1_##reg, offset, _id_offset, 9)
static
int
rsnd_gen1_regmap_init
(
struct
rsnd_priv
*
priv
,
struct
rsnd_gen
*
gen
)
{
struct
reg_field
regf
[
RSND_REG_MAX
]
=
{
RSND_GEN1_S_REG
(
gen
,
SRU
,
SRC_ROUTE_SEL
,
0x00
),
RSND_GEN1_S_REG
(
gen
,
SRU
,
SRC_TMG_SEL0
,
0x08
),
RSND_GEN1_S_REG
(
gen
,
SRU
,
SRC_TMG_SEL1
,
0x0c
),
RSND_GEN1_S_REG
(
gen
,
SRU
,
SRC_TMG_SEL2
,
0x10
),
RSND_GEN1_S_REG
(
gen
,
SRU
,
SRC_ROUTE_CTRL
,
0xc0
),
RSND_GEN1_S_REG
(
gen
,
SRU
,
SSI_MODE0
,
0xD0
),
RSND_GEN1_S_REG
(
gen
,
SRU
,
SSI_MODE1
,
0xD4
),
RSND_GEN1_M_REG
(
gen
,
SRU
,
SRC_BUSIF_MODE
,
0x20
,
0x4
),
RSND_GEN1_M_REG
(
gen
,
SRU
,
SRC_ROUTE_MODE0
,
0x50
,
0x8
),
RSND_GEN1_M_REG
(
gen
,
SRU
,
SRC_SWRSR
,
0x200
,
0x40
),
RSND_GEN1_M_REG
(
gen
,
SRU
,
SRC_SRCIR
,
0x204
,
0x40
),
RSND_GEN1_M_REG
(
gen
,
SRU
,
SRC_ADINR
,
0x214
,
0x40
),
RSND_GEN1_M_REG
(
gen
,
SRU
,
SRC_IFSCR
,
0x21c
,
0x40
),
RSND_GEN1_M_REG
(
gen
,
SRU
,
SRC_IFSVR
,
0x220
,
0x40
),
RSND_GEN1_M_REG
(
gen
,
SRU
,
SRC_SRCCR
,
0x224
,
0x40
),
RSND_GEN1_M_REG
(
gen
,
SRU
,
SRC_MNFSR
,
0x228
,
0x40
),
RSND_GEN1_S_REG
(
gen
,
ADG
,
BRRA
,
0x00
),
RSND_GEN1_S_REG
(
gen
,
ADG
,
BRRB
,
0x04
),
RSND_GEN1_S_REG
(
gen
,
ADG
,
SSICKR
,
0x08
),
RSND_GEN1_S_REG
(
gen
,
ADG
,
AUDIO_CLK_SEL0
,
0x0c
),
RSND_GEN1_S_REG
(
gen
,
ADG
,
AUDIO_CLK_SEL1
,
0x10
),
RSND_GEN1_S_REG
(
gen
,
ADG
,
AUDIO_CLK_SEL3
,
0x18
),
RSND_GEN1_S_REG
(
gen
,
ADG
,
AUDIO_CLK_SEL4
,
0x1c
),
RSND_GEN1_S_REG
(
gen
,
ADG
,
AUDIO_CLK_SEL5
,
0x20
),
RSND_GEN1_M_REG
(
gen
,
SSI
,
SSICR
,
0x00
,
0x40
),
RSND_GEN1_M_REG
(
gen
,
SSI
,
SSISR
,
0x04
,
0x40
),
RSND_GEN1_M_REG
(
gen
,
SSI
,
SSITDR
,
0x08
,
0x40
),
RSND_GEN1_M_REG
(
gen
,
SSI
,
SSIRDR
,
0x0c
,
0x40
),
RSND_GEN1_M_REG
(
gen
,
SSI
,
SSIWSR
,
0x20
,
0x40
),
};
return
rsnd_gen_regmap_init
(
priv
,
gen
,
regf
);
}
static
int
rsnd_gen1_probe
(
struct
platform_device
*
pdev
,
static
int
rsnd_gen1_probe
(
struct
platform_device
*
pdev
,
struct
rsnd_priv
*
priv
)
struct
rsnd_priv
*
priv
)
{
{
struct
device
*
dev
=
rsnd_priv_to_dev
(
priv
);
struct
device
*
dev
=
rsnd_priv_to_dev
(
priv
);
struct
rsnd_gen
*
gen
=
rsnd_priv_to_gen
(
priv
);
struct
rsnd_regmap_field_conf
conf_sru
[]
=
{
struct
resource
*
sru_res
;
RSND_GEN_S_REG
(
SRC_ROUTE_SEL
,
0x00
),
struct
resource
*
adg_res
;
RSND_GEN_S_REG
(
SRC_TMG_SEL0
,
0x08
),
struct
resource
*
ssi_res
;
RSND_GEN_S_REG
(
SRC_TMG_SEL1
,
0x0c
),
int
ret
;
RSND_GEN_S_REG
(
SRC_TMG_SEL2
,
0x10
),
RSND_GEN_S_REG
(
SRC_ROUTE_CTRL
,
0xc0
),
/*
RSND_GEN_S_REG
(
SSI_MODE0
,
0xD0
),
* map address
RSND_GEN_S_REG
(
SSI_MODE1
,
0xD4
),
*/
RSND_GEN_M_REG
(
SRC_BUSIF_MODE
,
0x20
,
0x4
),
sru_res
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
RSND_GEN1_SRU
);
RSND_GEN_M_REG
(
SRC_ROUTE_MODE0
,
0x50
,
0x8
),
adg_res
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
RSND_GEN1_ADG
);
RSND_GEN_M_REG
(
SRC_SWRSR
,
0x200
,
0x40
),
ssi_res
=
platform_get_resource
(
pdev
,
IORESOURCE_MEM
,
RSND_GEN1_SSI
);
RSND_GEN_M_REG
(
SRC_SRCIR
,
0x204
,
0x40
),
RSND_GEN_M_REG
(
SRC_ADINR
,
0x214
,
0x40
),
gen
->
base
[
RSND_GEN1_SRU
]
=
devm_ioremap_resource
(
dev
,
sru_res
);
RSND_GEN_M_REG
(
SRC_IFSCR
,
0x21c
,
0x40
),
gen
->
base
[
RSND_GEN1_ADG
]
=
devm_ioremap_resource
(
dev
,
adg_res
);
RSND_GEN_M_REG
(
SRC_IFSVR
,
0x220
,
0x40
),
gen
->
base
[
RSND_GEN1_SSI
]
=
devm_ioremap_resource
(
dev
,
ssi_res
);
RSND_GEN_M_REG
(
SRC_SRCCR
,
0x224
,
0x40
),
if
(
IS_ERR
(
gen
->
base
[
RSND_GEN1_SRU
])
||
RSND_GEN_M_REG
(
SRC_MNFSR
,
0x228
,
0x40
),
IS_ERR
(
gen
->
base
[
RSND_GEN1_ADG
])
||
};
IS_ERR
(
gen
->
base
[
RSND_GEN1_SSI
]))
struct
rsnd_regmap_field_conf
conf_adg
[]
=
{
return
-
ENODEV
;
RSND_GEN_S_REG
(
BRRA
,
0x00
),
RSND_GEN_S_REG
(
BRRB
,
0x04
),
RSND_GEN_S_REG
(
SSICKR
,
0x08
),
RSND_GEN_S_REG
(
AUDIO_CLK_SEL0
,
0x0c
),
RSND_GEN_S_REG
(
AUDIO_CLK_SEL1
,
0x10
),
RSND_GEN_S_REG
(
AUDIO_CLK_SEL3
,
0x18
),
RSND_GEN_S_REG
(
AUDIO_CLK_SEL4
,
0x1c
),
RSND_GEN_S_REG
(
AUDIO_CLK_SEL5
,
0x20
),
};
struct
rsnd_regmap_field_conf
conf_ssi
[]
=
{
RSND_GEN_M_REG
(
SSICR
,
0x00
,
0x40
),
RSND_GEN_M_REG
(
SSISR
,
0x04
,
0x40
),
RSND_GEN_M_REG
(
SSITDR
,
0x08
,
0x40
),
RSND_GEN_M_REG
(
SSIRDR
,
0x0c
,
0x40
),
RSND_GEN_M_REG
(
SSIWSR
,
0x20
,
0x40
),
};
int
ret_sru
;
int
ret_adg
;
int
ret_ssi
;
ret
=
rsnd_gen1_regmap_init
(
priv
,
gen
);
ret_sru
=
rsnd_gen_regmap_init
(
priv
,
9
,
RSND_GEN1_SRU
,
conf_sru
);
if
(
ret
<
0
)
ret_adg
=
rsnd_gen_regmap_init
(
priv
,
9
,
RSND_GEN1_ADG
,
conf_adg
);
return
ret
;
ret_ssi
=
rsnd_gen_regmap_init
(
priv
,
9
,
RSND_GEN1_SSI
,
conf_ssi
);
if
(
ret_sru
<
0
||
ret_adg
<
0
||
ret_ssi
<
0
)
return
ret_sru
|
ret_adg
|
ret_ssi
;
dev_dbg
(
dev
,
"Gen1 device probed
\n
"
);
dev_dbg
(
dev
,
"Gen1 is probed
\n
"
);
dev_dbg
(
dev
,
"SRU : %pap => %p
\n
"
,
&
sru_res
->
start
,
gen
->
base
[
RSND_GEN1_SRU
]);
dev_dbg
(
dev
,
"ADG : %pap => %p
\n
"
,
&
adg_res
->
start
,
gen
->
base
[
RSND_GEN1_ADG
]);
dev_dbg
(
dev
,
"SSI : %pap => %p
\n
"
,
&
ssi_res
->
start
,
gen
->
base
[
RSND_GEN1_SSI
]);
return
0
;
return
0
;
}
}
/*
/*
...
...
sound/soc/sh/rcar/rsnd.h
浏览文件 @
2fd53734
...
@@ -90,6 +90,7 @@ enum rsnd_reg {
...
@@ -90,6 +90,7 @@ enum rsnd_reg {
RSND_REG_SHARE19
,
RSND_REG_SHARE19
,
RSND_REG_SHARE20
,
RSND_REG_SHARE20
,
RSND_REG_SHARE21
,
RSND_REG_SHARE21
,
RSND_REG_SHARE22
,
RSND_REG_MAX
,
RSND_REG_MAX
,
};
};
...
@@ -127,6 +128,7 @@ enum rsnd_reg {
...
@@ -127,6 +128,7 @@ enum rsnd_reg {
#define RSND_REG_AUDIO_CLK_SEL2 RSND_REG_SHARE19
#define RSND_REG_AUDIO_CLK_SEL2 RSND_REG_SHARE19
#define RSND_REG_CMD_CTRL RSND_REG_SHARE20
#define RSND_REG_CMD_CTRL RSND_REG_SHARE20
#define RSND_REG_CMDOUT_TIMSEL RSND_REG_SHARE21
#define RSND_REG_CMDOUT_TIMSEL RSND_REG_SHARE21
#define RSND_REG_BUSIF_DALIGN RSND_REG_SHARE22
struct
rsnd_of_data
;
struct
rsnd_of_data
;
struct
rsnd_priv
;
struct
rsnd_priv
;
...
@@ -156,12 +158,9 @@ u32 rsnd_get_adinr(struct rsnd_mod *mod);
...
@@ -156,12 +158,9 @@ u32 rsnd_get_adinr(struct rsnd_mod *mod);
*/
*/
struct
rsnd_dma
{
struct
rsnd_dma
{
struct
sh_dmae_slave
slave
;
struct
sh_dmae_slave
slave
;
struct
work_struct
work
;
struct
dma_chan
*
chan
;
struct
dma_chan
*
chan
;
enum
dma_data_direction
dir
;
enum
dma_transfer_direction
dir
;
dma_addr_t
addr
;
int
submit_loop
;
int
offset
;
/* it cares A/B plane */
};
};
void
rsnd_dma_start
(
struct
rsnd_dma
*
dma
);
void
rsnd_dma_start
(
struct
rsnd_dma
*
dma
);
...
@@ -185,6 +184,7 @@ enum rsnd_mod_type {
...
@@ -185,6 +184,7 @@ enum rsnd_mod_type {
struct
rsnd_mod_ops
{
struct
rsnd_mod_ops
{
char
*
name
;
char
*
name
;
char
*
(
*
dma_name
)(
struct
rsnd_mod
*
mod
);
int
(
*
probe
)(
struct
rsnd_mod
*
mod
,
int
(
*
probe
)(
struct
rsnd_mod
*
mod
,
struct
rsnd_dai
*
rdai
);
struct
rsnd_dai
*
rdai
);
int
(
*
remove
)(
struct
rsnd_mod
*
mod
,
int
(
*
remove
)(
struct
rsnd_mod
*
mod
,
...
@@ -224,6 +224,7 @@ void rsnd_mod_init(struct rsnd_priv *priv,
...
@@ -224,6 +224,7 @@ void rsnd_mod_init(struct rsnd_priv *priv,
enum
rsnd_mod_type
type
,
enum
rsnd_mod_type
type
,
int
id
);
int
id
);
char
*
rsnd_mod_name
(
struct
rsnd_mod
*
mod
);
char
*
rsnd_mod_name
(
struct
rsnd_mod
*
mod
);
char
*
rsnd_mod_dma_name
(
struct
rsnd_mod
*
mod
);
/*
/*
* R-Car sound DAI
* R-Car sound DAI
...
@@ -281,10 +282,9 @@ int rsnd_gen_probe(struct platform_device *pdev,
...
@@ -281,10 +282,9 @@ int rsnd_gen_probe(struct platform_device *pdev,
void
__iomem
*
rsnd_gen_reg_get
(
struct
rsnd_priv
*
priv
,
void
__iomem
*
rsnd_gen_reg_get
(
struct
rsnd_priv
*
priv
,
struct
rsnd_mod
*
mod
,
struct
rsnd_mod
*
mod
,
enum
rsnd_reg
reg
);
enum
rsnd_reg
reg
);
void
rsnd_gen_dma_addr
(
struct
rsnd_priv
*
priv
,
dma_addr_t
rsnd_gen_dma_addr
(
struct
rsnd_priv
*
priv
,
struct
rsnd_dma
*
dma
,
struct
rsnd_mod
*
mod
,
struct
dma_slave_config
*
cfg
,
int
is_play
,
int
is_from
);
int
is_play
,
int
slave_id
);
#define rsnd_is_gen1(s) (((s)->info->flags & RSND_GEN_MASK) == RSND_GEN1)
#define rsnd_is_gen1(s) (((s)->info->flags & RSND_GEN_MASK) == RSND_GEN1)
#define rsnd_is_gen2(s) (((s)->info->flags & RSND_GEN_MASK) == RSND_GEN2)
#define rsnd_is_gen2(s) (((s)->info->flags & RSND_GEN_MASK) == RSND_GEN2)
...
@@ -391,8 +391,12 @@ struct rsnd_mod *rsnd_src_mod_get(struct rsnd_priv *priv, int id);
...
@@ -391,8 +391,12 @@ struct rsnd_mod *rsnd_src_mod_get(struct rsnd_priv *priv, int id);
unsigned
int
rsnd_src_get_ssi_rate
(
struct
rsnd_priv
*
priv
,
unsigned
int
rsnd_src_get_ssi_rate
(
struct
rsnd_priv
*
priv
,
struct
rsnd_dai_stream
*
io
,
struct
rsnd_dai_stream
*
io
,
struct
snd_pcm_runtime
*
runtime
);
struct
snd_pcm_runtime
*
runtime
);
int
rsnd_src_ssi_mode_init
(
struct
rsnd_mod
*
ssi_mod
,
int
rsnd_src_ssiu_start
(
struct
rsnd_mod
*
ssi_mod
,
struct
rsnd_dai
*
rdai
);
struct
rsnd_dai
*
rdai
,
int
use_busif
);
int
rsnd_src_ssiu_stop
(
struct
rsnd_mod
*
ssi_mod
,
struct
rsnd_dai
*
rdai
,
int
use_busif
);
int
rsnd_src_enable_ssi_irq
(
struct
rsnd_mod
*
ssi_mod
,
int
rsnd_src_enable_ssi_irq
(
struct
rsnd_mod
*
ssi_mod
,
struct
rsnd_dai
*
rdai
);
struct
rsnd_dai
*
rdai
);
...
...
sound/soc/sh/rcar/src.c
浏览文件 @
2fd53734
...
@@ -106,18 +106,19 @@ struct rsnd_src {
...
@@ -106,18 +106,19 @@ struct rsnd_src {
/*
/*
* Gen1/Gen2 common functions
* Gen1/Gen2 common functions
*/
*/
int
rsnd_src_ssi_mode_init
(
struct
rsnd_mod
*
ssi_mod
,
int
rsnd_src_ssiu_start
(
struct
rsnd_mod
*
ssi_mod
,
struct
rsnd_dai
*
rdai
)
struct
rsnd_dai
*
rdai
,
int
use_busif
)
{
{
struct
rsnd_dai_stream
*
io
=
rsnd_mod_to_io
(
ssi_mod
);
struct
rsnd_dai_stream
*
io
=
rsnd_mod_to_io
(
ssi_mod
);
struct
rsnd_mod
*
src_mod
=
rsnd_io_to_mod_src
(
io
);
struct
snd_pcm_runtime
*
runtime
=
rsnd_io_to_runtime
(
io
);
int
ssi_id
=
rsnd_mod_id
(
ssi_mod
);
int
ssi_id
=
rsnd_mod_id
(
ssi_mod
);
/*
/*
* SSI_MODE0
* SSI_MODE0
*/
*/
rsnd_mod_bset
(
ssi_mod
,
SSI_MODE0
,
(
1
<<
ssi_id
),
rsnd_mod_bset
(
ssi_mod
,
SSI_MODE0
,
(
1
<<
ssi_id
),
src_mod
?
0
:
(
1
<<
ssi_id
)
);
!
use_busif
<<
ssi_id
);
/*
/*
* SSI_MODE1
* SSI_MODE1
...
@@ -143,6 +144,46 @@ int rsnd_src_ssi_mode_init(struct rsnd_mod *ssi_mod,
...
@@ -143,6 +144,46 @@ int rsnd_src_ssi_mode_init(struct rsnd_mod *ssi_mod,
0x2
<<
shift
:
0x1
<<
shift
);
0x2
<<
shift
:
0x1
<<
shift
);
}
}
/*
* DMA settings for SSIU
*/
if
(
use_busif
)
{
u32
val
=
0x76543210
;
u32
mask
=
~
0
;
rsnd_mod_write
(
ssi_mod
,
SSI_BUSIF_ADINR
,
rsnd_get_adinr
(
ssi_mod
));
rsnd_mod_write
(
ssi_mod
,
SSI_BUSIF_MODE
,
1
);
rsnd_mod_write
(
ssi_mod
,
SSI_CTRL
,
0x1
);
mask
<<=
runtime
->
channels
*
4
;
val
=
val
&
mask
;
switch
(
runtime
->
sample_bits
)
{
case
16
:
val
|=
0x67452301
&
~
mask
;
break
;
case
32
:
val
|=
0x76543210
&
~
mask
;
break
;
}
rsnd_mod_write
(
ssi_mod
,
BUSIF_DALIGN
,
val
);
}
return
0
;
}
int
rsnd_src_ssiu_stop
(
struct
rsnd_mod
*
ssi_mod
,
struct
rsnd_dai
*
rdai
,
int
use_busif
)
{
/*
* DMA settings for SSIU
*/
if
(
use_busif
)
rsnd_mod_write
(
ssi_mod
,
SSI_CTRL
,
0
);
return
0
;
return
0
;
}
}
...
@@ -461,18 +502,45 @@ static struct rsnd_mod_ops rsnd_src_gen1_ops = {
...
@@ -461,18 +502,45 @@ static struct rsnd_mod_ops rsnd_src_gen1_ops = {
static
int
rsnd_src_set_convert_rate_gen2
(
struct
rsnd_mod
*
mod
,
static
int
rsnd_src_set_convert_rate_gen2
(
struct
rsnd_mod
*
mod
,
struct
rsnd_dai
*
rdai
)
struct
rsnd_dai
*
rdai
)
{
{
struct
rsnd_priv
*
priv
=
rsnd_mod_to_priv
(
mod
);
struct
device
*
dev
=
rsnd_priv_to_dev
(
priv
);
struct
rsnd_dai_stream
*
io
=
rsnd_mod_to_io
(
mod
);
struct
snd_pcm_runtime
*
runtime
=
rsnd_io_to_runtime
(
io
);
struct
rsnd_src
*
src
=
rsnd_mod_to_src
(
mod
);
uint
ratio
;
int
ret
;
int
ret
;
/* 6 - 1/6 are very enough ratio for SRC_BSDSR */
if
(
!
rsnd_src_convert_rate
(
src
))
ratio
=
0
;
else
if
(
rsnd_src_convert_rate
(
src
)
>
runtime
->
rate
)
ratio
=
100
*
rsnd_src_convert_rate
(
src
)
/
runtime
->
rate
;
else
ratio
=
100
*
runtime
->
rate
/
rsnd_src_convert_rate
(
src
);
if
(
ratio
>
600
)
{
dev_err
(
dev
,
"FSO/FSI ratio error
\n
"
);
return
-
EINVAL
;
}
ret
=
rsnd_src_set_convert_rate
(
mod
,
rdai
);
ret
=
rsnd_src_set_convert_rate
(
mod
,
rdai
);
if
(
ret
<
0
)
if
(
ret
<
0
)
return
ret
;
return
ret
;
rsnd_mod_write
(
mod
,
SSI_BUSIF_ADINR
,
rsnd_get_adinr
(
mod
));
rsnd_mod_write
(
mod
,
SSI_BUSIF_MODE
,
1
);
rsnd_mod_write
(
mod
,
SRC_SRCCR
,
0x00011110
);
rsnd_mod_write
(
mod
,
SRC_SRCCR
,
0x00011110
);
switch
(
rsnd_mod_id
(
mod
))
{
case
5
:
case
6
:
case
7
:
case
8
:
rsnd_mod_write
(
mod
,
SRC_BSDSR
,
0x02400000
);
break
;
default:
rsnd_mod_write
(
mod
,
SRC_BSDSR
,
0x01800000
);
rsnd_mod_write
(
mod
,
SRC_BSDSR
,
0x01800000
);
break
;
}
rsnd_mod_write
(
mod
,
SRC_BSISR
,
0x00100060
);
rsnd_mod_write
(
mod
,
SRC_BSISR
,
0x00100060
);
return
0
;
return
0
;
...
@@ -554,7 +622,6 @@ static int rsnd_src_start_gen2(struct rsnd_mod *mod,
...
@@ -554,7 +622,6 @@ static int rsnd_src_start_gen2(struct rsnd_mod *mod,
rsnd_dma_start
(
rsnd_mod_to_dma
(
&
src
->
mod
));
rsnd_dma_start
(
rsnd_mod_to_dma
(
&
src
->
mod
));
rsnd_mod_write
(
mod
,
SSI_CTRL
,
0x1
);
rsnd_mod_write
(
mod
,
SRC_CTRL
,
val
);
rsnd_mod_write
(
mod
,
SRC_CTRL
,
val
);
return
rsnd_src_start
(
mod
,
rdai
);
return
rsnd_src_start
(
mod
,
rdai
);
...
@@ -565,7 +632,6 @@ static int rsnd_src_stop_gen2(struct rsnd_mod *mod,
...
@@ -565,7 +632,6 @@ static int rsnd_src_stop_gen2(struct rsnd_mod *mod,
{
{
struct
rsnd_src
*
src
=
rsnd_mod_to_src
(
mod
);
struct
rsnd_src
*
src
=
rsnd_mod_to_src
(
mod
);
rsnd_mod_write
(
mod
,
SSI_CTRL
,
0
);
rsnd_mod_write
(
mod
,
SRC_CTRL
,
0
);
rsnd_mod_write
(
mod
,
SRC_CTRL
,
0
);
rsnd_dma_stop
(
rsnd_mod_to_dma
(
&
src
->
mod
));
rsnd_dma_stop
(
rsnd_mod_to_dma
(
&
src
->
mod
));
...
...
sound/soc/sh/rcar/ssi.c
浏览文件 @
2fd53734
...
@@ -90,6 +90,20 @@ struct rsnd_ssi {
...
@@ -90,6 +90,20 @@ struct rsnd_ssi {
#define rsnd_ssi_mode_flags(p) ((p)->info->flags)
#define rsnd_ssi_mode_flags(p) ((p)->info->flags)
#define rsnd_ssi_dai_id(ssi) ((ssi)->info->dai_id)
#define rsnd_ssi_dai_id(ssi) ((ssi)->info->dai_id)
static
int
rsnd_ssi_use_busif
(
struct
rsnd_mod
*
mod
)
{
struct
rsnd_ssi
*
ssi
=
rsnd_mod_to_ssi
(
mod
);
struct
rsnd_dai_stream
*
io
=
rsnd_mod_to_io
(
mod
);
int
use_busif
=
0
;
if
(
!
(
rsnd_ssi_mode_flags
(
ssi
)
&
RSND_SSI_NO_BUSIF
))
use_busif
=
1
;
if
(
rsnd_io_to_mod_src
(
io
))
use_busif
=
1
;
return
use_busif
;
}
static
void
rsnd_ssi_status_check
(
struct
rsnd_mod
*
mod
,
static
void
rsnd_ssi_status_check
(
struct
rsnd_mod
*
mod
,
u32
bit
)
u32
bit
)
{
{
...
@@ -289,8 +303,6 @@ static int rsnd_ssi_init(struct rsnd_mod *mod,
...
@@ -289,8 +303,6 @@ static int rsnd_ssi_init(struct rsnd_mod *mod,
ssi
->
cr_own
=
cr
;
ssi
->
cr_own
=
cr
;
ssi
->
err
=
-
1
;
/* ignore 1st error */
ssi
->
err
=
-
1
;
/* ignore 1st error */
rsnd_src_ssi_mode_init
(
mod
,
rdai
);
return
0
;
return
0
;
}
}
...
@@ -389,6 +401,8 @@ static int rsnd_ssi_pio_start(struct rsnd_mod *mod,
...
@@ -389,6 +401,8 @@ static int rsnd_ssi_pio_start(struct rsnd_mod *mod,
/* enable PIO IRQ */
/* enable PIO IRQ */
ssi
->
cr_etc
=
UIEN
|
OIEN
|
DIEN
;
ssi
->
cr_etc
=
UIEN
|
OIEN
|
DIEN
;
rsnd_src_ssiu_start
(
mod
,
rdai
,
0
);
rsnd_src_enable_ssi_irq
(
mod
,
rdai
);
rsnd_src_enable_ssi_irq
(
mod
,
rdai
);
rsnd_ssi_hw_start
(
ssi
,
rdai
,
io
);
rsnd_ssi_hw_start
(
ssi
,
rdai
,
io
);
...
@@ -405,6 +419,8 @@ static int rsnd_ssi_pio_stop(struct rsnd_mod *mod,
...
@@ -405,6 +419,8 @@ static int rsnd_ssi_pio_stop(struct rsnd_mod *mod,
rsnd_ssi_hw_stop
(
ssi
,
rdai
);
rsnd_ssi_hw_stop
(
ssi
,
rdai
);
rsnd_src_ssiu_stop
(
mod
,
rdai
,
0
);
return
0
;
return
0
;
}
}
...
@@ -457,6 +473,8 @@ static int rsnd_ssi_dma_start(struct rsnd_mod *mod,
...
@@ -457,6 +473,8 @@ static int rsnd_ssi_dma_start(struct rsnd_mod *mod,
/* enable DMA transfer */
/* enable DMA transfer */
ssi
->
cr_etc
=
DMEN
;
ssi
->
cr_etc
=
DMEN
;
rsnd_src_ssiu_start
(
mod
,
rdai
,
rsnd_ssi_use_busif
(
mod
));
rsnd_dma_start
(
dma
);
rsnd_dma_start
(
dma
);
rsnd_ssi_hw_start
(
ssi
,
ssi
->
rdai
,
io
);
rsnd_ssi_hw_start
(
ssi
,
ssi
->
rdai
,
io
);
...
@@ -482,11 +500,19 @@ static int rsnd_ssi_dma_stop(struct rsnd_mod *mod,
...
@@ -482,11 +500,19 @@ static int rsnd_ssi_dma_stop(struct rsnd_mod *mod,
rsnd_dma_stop
(
dma
);
rsnd_dma_stop
(
dma
);
rsnd_src_ssiu_stop
(
mod
,
rdai
,
1
);
return
0
;
return
0
;
}
}
static
char
*
rsnd_ssi_dma_name
(
struct
rsnd_mod
*
mod
)
{
return
rsnd_ssi_use_busif
(
mod
)
?
"ssiu"
:
SSI_NAME
;
}
static
struct
rsnd_mod_ops
rsnd_ssi_dma_ops
=
{
static
struct
rsnd_mod_ops
rsnd_ssi_dma_ops
=
{
.
name
=
SSI_NAME
,
.
name
=
SSI_NAME
,
.
dma_name
=
rsnd_ssi_dma_name
,
.
probe
=
rsnd_ssi_dma_probe
,
.
probe
=
rsnd_ssi_dma_probe
,
.
remove
=
rsnd_ssi_dma_remove
,
.
remove
=
rsnd_ssi_dma_remove
,
.
init
=
rsnd_ssi_init
,
.
init
=
rsnd_ssi_init
,
...
@@ -595,6 +621,9 @@ static void rsnd_of_parse_ssi(struct platform_device *pdev,
...
@@ -595,6 +621,9 @@ static void rsnd_of_parse_ssi(struct platform_device *pdev,
*/
*/
ssi_info
->
dma_id
=
of_get_property
(
np
,
"pio-transfer"
,
NULL
)
?
ssi_info
->
dma_id
=
of_get_property
(
np
,
"pio-transfer"
,
NULL
)
?
0
:
1
;
0
:
1
;
if
(
of_get_property
(
np
,
"no-busif"
,
NULL
))
ssi_info
->
flags
|=
RSND_SSI_NO_BUSIF
;
}
}
rsnd_of_parse_ssi_end:
rsnd_of_parse_ssi_end:
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录