Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
cloud-kernel
提交
2fd53734
cloud-kernel
项目概览
openanolis
/
cloud-kernel
1 年多 前同步成功
通知
160
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:
- rcar_sound,src : Should contain SRC feature.
The number of SRC subnode should be same as HW.
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.
The number of DAI subnode should be same as HW.
see below for detail.
...
...
@@ -21,6 +24,7 @@ SSI subnode properties:
- interrupts : Should contain SSI interrupt for PIO transfer
- shared-pin : if shared clock pin
- pio-transfer : use PIO transfer mode
- no-busif : BUSIF is not ussed when [mem -> SSI] via DMA case
SRC subnode properties:
no properties at this point
...
...
@@ -39,6 +43,11 @@ rcar_sound: rcar_sound@0xffd90000 {
<0 0xec540000 0 0x1000>, /* SSIU */
<0 0xec541000 0 0x1280>; /* SSI */
rcar_sound,dvc {
dvc0: dvc@0 { };
dvc1: dvc@1 { };
};
rcar_sound,src {
src0: src@0 { };
src1: src@1 { };
...
...
arch/arm/mach-shmobile/board-armadillo800eva.c
浏览文件 @
2fd53734
...
...
@@ -998,6 +998,8 @@ static struct platform_device fsi_wm8978_device = {
.
id
=
0
,
.
dev
=
{
.
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 = {
.
id
=
1
,
.
dev
=
{
.
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 = {
.
name
=
"asoc-simple-card"
,
.
dev
=
{
.
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 = {
.
id
=
1
,
.
dev
=
{
.
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 = {
.
name
=
"asoc-simple-card"
,
.
dev
=
{
.
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 = {
.
name
=
"asoc-simple-card"
,
.
dev
=
{
.
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 @@
* B : SSI direction
*/
#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) \
{ .dma_id = _dma_id, .pio_irq = _pio_irq, .flags = _flags }
...
...
sound/soc/sh/Kconfig
浏览文件 @
2fd53734
...
...
@@ -37,7 +37,7 @@ config SND_SOC_SH4_SIU
config SND_SOC_RCAR
tristate "R-Car series SRU/SCU/SSIU/SSI support"
select SND_SIMPLE_CARD
select REGMAP
select REGMAP
_MMIO
help
This option enables R-Car SUR/SCU/SSIU/SSI sound support
...
...
sound/soc/sh/fsi.c
浏览文件 @
2fd53734
...
...
@@ -232,11 +232,7 @@ struct fsi_stream {
* these are for DMAEngine
*/
struct
dma_chan
*
chan
;
struct
work_struct
work
;
dma_addr_t
dma
;
int
dma_id
;
int
loop_cnt
;
int
additional_pos
;
};
struct
fsi_clk
{
...
...
@@ -1042,6 +1038,26 @@ static int fsi_clk_set_rate_cpg(struct device *dev,
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
*/
...
...
@@ -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
),
int
samples
)
{
struct
snd_pcm_runtime
*
runtime
;
struct
snd_pcm_substream
*
substream
;
u8
*
buf
;
int
over_period
;
if
(
!
fsi_stream_is_working
(
fsi
,
io
))
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
);
switch
(
io
->
sample_width
)
{
...
...
@@ -1146,11 +1142,7 @@ static int fsi_pio_transfer(struct fsi_priv *fsi, struct fsi_stream *io,
return
-
EINVAL
;
}
/* update buff_sample_pos */
io
->
buff_sample_pos
+=
samples
;
if
(
over_period
)
snd_pcm_period_elapsed
(
substream
);
fsi_pointer_update
(
io
,
samples
);
return
0
;
}
...
...
@@ -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
)
{
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
* 16bit data : 16bit bus / stream mode
...
...
@@ -1291,107 +1278,48 @@ static int fsi_dma_init(struct fsi_priv *fsi, struct fsi_stream *io)
io
->
bus_option
=
BUSOP_SET
(
24
,
PACKAGE_24BITBUS_BACK
)
|
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
;
}
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
)
{
struct
fsi_stream
*
io
=
(
struct
fsi_stream
*
)
data
;
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
),
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_pointer_update
(
io
,
io
->
period_samples
);
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
fsi_priv
*
fsi
=
fsi_stream_to_priv
(
io
);
struct
snd_soc_dai
*
dai
;
struct
snd_soc_dai
*
dai
=
fsi_get_dai
(
io
->
substream
);
struct
snd_pcm_substream
*
substream
=
io
->
substream
;
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
len
,
i
;
dma_addr_t
buf
;
if
(
!
fsi_stream_is_working
(
fsi
,
io
))
return
;
dai
=
fsi_get_dai
(
io
->
substream
);
runtime
=
io
->
substream
->
runtime
;
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
);
if
(
!
desc
)
{
dev_err
(
dai
->
dev
,
"dmaengine_prep_slave_sg() fail
\n
"
);
return
;
}
desc
->
callback
=
fsi_dma_complete
;
desc
->
callback_param
=
io
;
if
(
dmaengine_submit
(
desc
)
<
0
)
{
dev_err
(
dai
->
dev
,
"tx_submit() fail
\n
"
);
return
;
}
enum
dma_data_direction
dir
=
is_play
?
DMA_TO_DEVICE
:
DMA_FROM_DEVICE
;
int
ret
=
-
EIO
;
desc
=
dmaengine_prep_dma_cyclic
(
io
->
chan
,
substream
->
runtime
->
dma_addr
,
snd_pcm_lib_buffer_bytes
(
substream
),
snd_pcm_lib_period_bytes
(
substream
),
dir
,
DMA_PREP_INTERRUPT
|
DMA_CTRL_ACK
);
if
(
!
desc
)
{
dev_err
(
dai
->
dev
,
"dmaengine_prep_dma_cyclic() fail
\n
"
);
goto
fsi_dma_transfer_err
;
}
dma_async_issue_pending
(
io
->
chan
);
desc
->
callback
=
fsi_dma_complete
;
desc
->
callback_param
=
io
;
io
->
additional_pos
=
1
;
if
(
dmaengine_submit
(
desc
)
<
0
)
{
dev_err
(
dai
->
dev
,
"tx_submit() fail
\n
"
);
goto
fsi_dma_transfer_err
;
}
io
->
loop_cnt
=
1
;
dma_async_issue_pending
(
io
->
chan
)
;
/*
* FIXME
...
...
@@ -1408,13 +1336,11 @@ static void fsi_dma_do_work(struct work_struct *work)
fsi_reg_write
(
fsi
,
DIFF_ST
,
0
);
}
}
}
static
int
fsi_dma_transfer
(
struct
fsi_priv
*
fsi
,
struct
fsi_stream
*
io
)
{
schedule_work
(
&
io
->
work
);
ret
=
0
;
return
0
;
fsi_dma_transfer_err:
return
ret
;
}
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
return
fsi_stream_probe
(
fsi
,
dev
);
}
INIT_WORK
(
&
io
->
work
,
fsi_dma_do_work
);
return
0
;
}
static
int
fsi_dma_remove
(
struct
fsi_priv
*
fsi
,
struct
fsi_stream
*
io
)
{
cancel_work_sync
(
&
io
->
work
);
fsi_stream_stop
(
fsi
,
io
);
if
(
io
->
chan
)
...
...
@@ -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
=
{
.
init
=
fsi_dma_init
,
.
quit
=
fsi_dma_quit
,
.
probe
=
fsi_dma_probe
,
.
transfer
=
fsi_dma_transfer
,
.
remove
=
fsi_dma_remove
,
...
...
@@ -1657,9 +1578,9 @@ static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd,
if
(
!
ret
)
ret
=
fsi_hw_startup
(
fsi
,
io
,
dai
->
dev
);
if
(
!
ret
)
ret
=
fsi_stream_
transfer
(
io
);
ret
=
fsi_stream_
start
(
fsi
,
io
);
if
(
!
ret
)
fsi_stream_start
(
fsi
,
io
);
ret
=
fsi_stream_transfer
(
io
);
break
;
case
SNDRV_PCM_TRIGGER_STOP
:
if
(
!
ret
)
...
...
@@ -1850,16 +1771,10 @@ static void fsi_pcm_free(struct snd_pcm *pcm)
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
(
pcm
,
SNDRV_DMA_TYPE_
CONTINUOUS
,
snd_dma_continuous_data
(
GFP_KERNEL
)
,
rtd
->
pcm
,
SNDRV_DMA_TYPE_
DEV
,
rtd
->
card
->
snd_card
->
dev
,
PREALLOC_BUFFER
,
PREALLOC_BUFFER_MAX
);
}
...
...
sound/soc/sh/rcar/core.c
浏览文件 @
2fd53734
...
...
@@ -138,6 +138,17 @@ char *rsnd_mod_name(struct rsnd_mod *mod)
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
,
struct
rsnd_mod
*
mod
,
struct
rsnd_mod_ops
*
ops
,
...
...
@@ -153,26 +164,8 @@ void rsnd_mod_init(struct rsnd_priv *priv,
/*
* 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
)
{
dma
->
submit_loop
=
0
;
cancel_work_sync
(
&
dma
->
work
);
dmaengine_terminate_all
(
dma
->
chan
);
}
...
...
@@ -180,11 +173,7 @@ static void rsnd_dma_complete(void *data)
{
struct
rsnd_dma
*
dma
=
(
struct
rsnd_dma
*
)
data
;
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
);
unsigned
long
flags
;
rsnd_lock
(
priv
,
flags
);
/*
* Renesas sound Gen1 needs 1 DMAC,
...
...
@@ -197,57 +186,41 @@ static void rsnd_dma_complete(void *data)
* rsnd_dai_pointer_update() will be called twice,
* 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
);
}
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_priv
*
priv
=
rsnd_mod_to_priv
(
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
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
++
)
{
buf
=
runtime
->
dma_addr
+
rsnd_dai_pointer_offset
(
io
,
dma
->
offset
+
len
);
dma
->
offset
=
len
;
desc
=
dmaengine_prep_slave_single
(
dma
->
chan
,
buf
,
len
,
dma
->
dir
,
DMA_PREP_INTERRUPT
|
DMA_CTRL_ACK
);
if
(
!
desc
)
{
dev_err
(
dev
,
"dmaengine_prep_slave_sg() fail
\n
"
);
return
;
}
desc
=
dmaengine_prep_dma_cyclic
(
dma
->
chan
,
(
dma
->
addr
)
?
dma
->
addr
:
substream
->
runtime
->
dma_addr
,
snd_pcm_lib_buffer_bytes
(
substream
),
snd_pcm_lib_period_bytes
(
substream
),
dma
->
dir
,
DMA_PREP_INTERRUPT
|
DMA_CTRL_ACK
);
desc
->
callback
=
rsnd_dma_complete
;
desc
->
callback_param
=
dma
;
if
(
!
desc
)
{
dev_err
(
dev
,
"dmaengine_prep_slave_sg() fail
\n
"
);
return
;
}
if
(
dmaengine_submit
(
desc
)
<
0
)
{
dev_err
(
dev
,
"dmaengine_submit() fail
\n
"
);
return
;
}
desc
->
callback
=
rsnd_dma_complete
;
desc
->
callback_param
=
dma
;
dma_async_issue_pending
(
dma
->
chan
);
if
(
dmaengine_submit
(
desc
)
<
0
)
{
dev_err
(
dev
,
"dmaengine_submit() fail
\n
"
);
return
;
}
}
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
);
dma_async_issue_pending
(
dma
->
chan
);
}
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)
{
if
(
mod
)
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
return
snprintf
(
dma_name
,
DMA_NAME_SIZE
/
2
,
"mem"
);
}
static
void
rsnd_dma_of_name
(
struct
rsnd_dma
*
dma
,
int
is_play
,
char
*
dma_name
)
static
void
rsnd_dma_of_name
(
struct
rsnd_mod
*
mod_from
,
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_dai_stream
*
io
=
rsnd_mod_to_io
(
this
);
...
...
@@ -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
*
dvc
=
rsnd_io_to_mod_dvc
(
io
);
struct
rsnd_mod
*
mod
[
MOD_MAX
];
struct
rsnd_mod
*
src_mod
,
*
dst_mod
;
int
i
,
index
;
...
...
@@ -301,7 +286,13 @@ static void rsnd_dma_of_name(struct rsnd_dma *dma,
mod
[
i
]
=
src
;
src
=
NULL
;
}
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
;
}
...
...
@@ -313,17 +304,12 @@ static void rsnd_dma_of_name(struct rsnd_dma *dma,
}
if
(
is_play
)
{
src_mod
=
mod
[
index
-
1
];
dst_mod
=
mod
[
index
];
*
mod_from
=
mod
[
index
-
1
];
*
mod_to
=
mod
[
index
];
}
else
{
src_mod
=
mod
[
index
];
dst_mod
=
mod
[
index
-
1
];
*
mod_from
=
mod
[
index
];
*
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
,
...
...
@@ -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
dma_slave_config
cfg
;
struct
rsnd_mod
*
mod_from
;
struct
rsnd_mod
*
mod_to
;
char
dma_name
[
DMA_NAME_SIZE
];
dma_cap_mask_t
mask
;
int
ret
;
...
...
@@ -343,13 +331,18 @@ int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma,
dma_cap_zero
(
mask
);
dma_cap_set
(
DMA_SLAVE
,
mask
);
if
(
dev
->
of_node
)
rsnd_dma_of_name
(
dma
,
is_play
,
dma_name
);
else
snprintf
(
dma_name
,
DMA_NAME_SIZE
,
is_play
?
"tx"
:
"rx"
);
rsnd_dma_of_path
(
dma
,
is_play
,
&
mod_from
,
&
mod_to
);
rsnd_dma_of_name
(
mod_from
,
mod_to
,
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 name : %s
\n
"
,
dma_name
);
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
,
(
void
*
)
id
,
dev
,
...
...
@@ -359,14 +352,12 @@ int rsnd_dma_init(struct rsnd_priv *priv, struct rsnd_dma *dma,
return
-
EIO
;
}
rsnd_gen_dma_addr
(
priv
,
dma
,
&
cfg
,
is_play
,
id
);
ret
=
dmaengine_slave_config
(
dma
->
chan
,
&
cfg
);
if
(
ret
<
0
)
goto
rsnd_dma_init_err
;
dma
->
dir
=
is_play
?
DMA_TO_DEVICE
:
DMA_FROM_DEVICE
;
INIT_WORK
(
&
dma
->
work
,
rsnd_dma_do_work
)
;
dma
->
addr
=
is_play
?
cfg
.
src_addr
:
cfg
.
dst_addr
;
dma
->
dir
=
is_play
?
DMA_MEM_TO_DEV
:
DMA_DEV_TO_MEM
;
return
0
;
...
...
@@ -633,40 +624,41 @@ static int rsnd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
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 */
switch
(
fmt
&
SND_SOC_DAIFMT_FORMAT_MASK
)
{
case
SND_SOC_DAIFMT_I2S
:
rdai
->
sys_delay
=
0
;
rdai
->
data_alignment
=
0
;
rdai
->
frm_clk_inv
=
0
;
break
;
case
SND_SOC_DAIFMT_LEFT_J
:
rdai
->
sys_delay
=
1
;
rdai
->
data_alignment
=
0
;
rdai
->
frm_clk_inv
=
1
;
break
;
case
SND_SOC_DAIFMT_RIGHT_J
:
rdai
->
sys_delay
=
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
;
}
...
...
@@ -736,12 +728,13 @@ static void rsnd_of_parse_dai(struct platform_device *pdev,
struct
device_node
*
dai_node
,
*
dai_np
;
struct
device_node
*
ssi_node
,
*
ssi_np
;
struct
device_node
*
src_node
,
*
src_np
;
struct
device_node
*
dvc_node
,
*
dvc_np
;
struct
device_node
*
playback
,
*
capture
;
struct
rsnd_dai_platform_info
*
dai_info
;
struct
rcar_snd_info
*
info
=
rsnd_priv_to_info
(
priv
);
struct
device
*
dev
=
&
pdev
->
dev
;
int
nr
,
i
;
int
dai_i
,
ssi_i
,
src_i
;
int
dai_i
,
ssi_i
,
src_i
,
dvc_i
;
if
(
!
of_data
)
return
;
...
...
@@ -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"
);
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) \
if (name##_node) { \
...
...
@@ -802,6 +796,7 @@ if (name##_node) { \
mod_parse
(
ssi
);
mod_parse
(
src
);
mod_parse
(
dvc
);
if
(
playback
)
of_node_put
(
playback
);
...
...
@@ -950,19 +945,17 @@ static struct snd_pcm_ops rsnd_pcm_ops = {
static
int
rsnd_pcm_new
(
struct
snd_soc_pcm_runtime
*
rtd
)
{
struct
rsnd_priv
*
priv
=
snd_soc_dai_get_drvdata
(
rtd
->
cpu_dai
)
;
struct
rsnd_dai
*
rdai
;
int
i
,
ret
;
struct
snd_soc_dai
*
dai
=
rtd
->
cpu_dai
;
struct
rsnd_dai
*
rdai
=
rsnd_dai_to_rdai
(
dai
)
;
int
ret
;
for_each_rsnd_dai
(
rdai
,
priv
,
i
)
{
ret
=
rsnd_dai_call
(
pcm_new
,
&
rdai
->
playback
,
rdai
,
rtd
);
if
(
ret
)
return
ret
;
ret
=
rsnd_dai_call
(
pcm_new
,
&
rdai
->
playback
,
rdai
,
rtd
);
if
(
ret
)
return
ret
;
ret
=
rsnd_dai_call
(
pcm_new
,
&
rdai
->
capture
,
rdai
,
rtd
);
if
(
ret
)
return
ret
;
}
ret
=
rsnd_dai_call
(
pcm_new
,
&
rdai
->
capture
,
rdai
,
rtd
);
if
(
ret
)
return
ret
;
return
snd_pcm_lib_preallocate_pages_for_all
(
rtd
->
pcm
,
...
...
@@ -1049,11 +1042,11 @@ static int rsnd_probe(struct platform_device *pdev)
for_each_rsnd_dai
(
rdai
,
priv
,
i
)
{
ret
=
rsnd_dai_call
(
probe
,
&
rdai
->
playback
,
rdai
);
if
(
ret
)
return
ret
;
goto
exit_snd_probe
;
ret
=
rsnd_dai_call
(
probe
,
&
rdai
->
capture
,
rdai
);
if
(
ret
)
return
ret
;
goto
exit_snd_probe
;
}
/*
...
...
@@ -1081,6 +1074,11 @@ static int rsnd_probe(struct platform_device *pdev)
exit_snd_soc:
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
;
}
...
...
@@ -1089,21 +1087,16 @@ static int rsnd_remove(struct platform_device *pdev)
{
struct
rsnd_priv
*
priv
=
dev_get_drvdata
(
&
pdev
->
dev
);
struct
rsnd_dai
*
rdai
;
int
ret
,
i
;
int
ret
=
0
,
i
;
pm_runtime_disable
(
&
pdev
->
dev
);
for_each_rsnd_dai
(
rdai
,
priv
,
i
)
{
ret
=
rsnd_dai_call
(
remove
,
&
rdai
->
playback
,
rdai
);
if
(
ret
)
return
ret
;
ret
=
rsnd_dai_call
(
remove
,
&
rdai
->
capture
,
rdai
);
if
(
ret
)
return
ret
;
ret
|=
rsnd_dai_call
(
remove
,
&
rdai
->
playback
,
rdai
);
ret
|=
rsnd_dai_call
(
remove
,
&
rdai
->
capture
,
rdai
);
}
return
0
;
return
ret
;
}
static
struct
platform_driver
rsnd_driver
=
{
...
...
sound/soc/sh/rcar/dvc.c
浏览文件 @
2fd53734
...
...
@@ -20,7 +20,8 @@ struct rsnd_dvc {
struct
rsnd_dvc_platform_info
*
info
;
/* rcar_snd.h */
struct
rsnd_mod
mod
;
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) \
...
...
@@ -37,13 +38,18 @@ static void rsnd_dvc_volume_update(struct rsnd_mod *mod)
struct
rsnd_dvc
*
dvc
=
rsnd_mod_to_dvc
(
mod
);
u32
max
=
(
0x00800000
-
1
);
u32
vol
[
RSND_DVC_VOLUME_NUM
];
u32
mute
=
0
;
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
];
mute
|=
(
!!
dvc
->
mute
[
i
])
<<
i
;
}
rsnd_mod_write
(
mod
,
DVC_VOL0R
,
vol
[
0
]);
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
,
...
...
@@ -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
));
/* enable Volume */
rsnd_mod_write
(
dvc_mod
,
DVC_DVUCR
,
0x10
0
);
/* enable Volume
/ Mute
*/
rsnd_mod_write
(
dvc_mod
,
DVC_DVUCR
,
0x10
1
);
/* ch0/ch1 Volume */
rsnd_dvc_volume_update
(
dvc_mod
);
...
...
@@ -140,10 +146,20 @@ static int rsnd_dvc_stop(struct rsnd_mod *mod,
static
int
rsnd_dvc_volume_info
(
struct
snd_kcontrol
*
kctrl
,
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
->
value
.
integer
.
min
=
0
;
uinfo
->
value
.
integer
.
max
=
RSND_DVC_VOLUME_MAX
;
if
(
val
==
dvc
->
volume
)
{
uinfo
->
type
=
SNDRV_CTL_ELEM_TYPE_INTEGER
;
uinfo
->
value
.
integer
.
max
=
RSND_DVC_VOLUME_MAX
;
}
else
{
uinfo
->
type
=
SNDRV_CTL_ELEM_TYPE_BOOLEAN
;
uinfo
->
value
.
integer
.
max
=
1
;
}
return
0
;
}
...
...
@@ -151,12 +167,11 @@ static int rsnd_dvc_volume_info(struct snd_kcontrol *kctrl,
static
int
rsnd_dvc_volume_get
(
struct
snd_kcontrol
*
kctrl
,
struct
snd_ctl_elem_value
*
ucontrol
)
{
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
;
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
;
}
...
...
@@ -165,51 +180,38 @@ static int rsnd_dvc_volume_put(struct snd_kcontrol *kctrl,
struct
snd_ctl_elem_value
*
ucontrol
)
{
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
;
for
(
i
=
0
;
i
<
RSND_DVC_VOLUME_NUM
;
i
++
)
{
if
(
ucontrol
->
value
.
integer
.
value
[
i
]
<
0
||
ucontrol
->
value
.
integer
.
value
[
i
]
>
RSND_DVC_VOLUME_MAX
)
return
-
EINVAL
;
change
|=
(
ucontrol
->
value
.
integer
.
value
[
i
]
!=
dvc
->
volume
[
i
]);
change
|=
(
ucontrol
->
value
.
integer
.
value
[
i
]
!=
val
[
i
]);
val
[
i
]
=
ucontrol
->
value
.
integer
.
value
[
i
];
}
if
(
change
)
{
for
(
i
=
0
;
i
<
RSND_DVC_VOLUME_NUM
;
i
++
)
dvc
->
volume
[
i
]
=
ucontrol
->
value
.
integer
.
value
[
i
];
if
(
change
)
rsnd_dvc_volume_update
(
mod
);
}
return
change
;
}
static
int
rsnd_dvc_pcm_new
(
struct
rsnd_mod
*
mod
,
struct
rsnd_dai
*
rdai
,
struct
snd_soc_pcm_runtime
*
rtd
)
static
int
__rsnd_dvc_pcm_new
(
struct
rsnd_mod
*
mod
,
struct
rsnd_dai
*
rdai
,
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_kcontrol
*
kctrl
;
st
atic
st
ruct
snd_kcontrol_new
knew
=
{
struct
snd_kcontrol_new
knew
=
{
.
iface
=
SNDRV_CTL_ELEM_IFACE_MIXER
,
.
name
=
"Playback Volume"
,
.
name
=
name
,
.
info
=
rsnd_dvc_volume_info
,
.
get
=
rsnd_dvc_volume_get
,
.
put
=
rsnd_dvc_volume_put
,
.
private_value
=
(
unsigned
long
)
private
,
};
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
);
if
(
!
kctrl
)
return
-
ENOMEM
;
...
...
@@ -221,6 +223,33 @@ static int rsnd_dvc_pcm_new(struct rsnd_mod *mod,
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
=
{
.
name
=
DVC_NAME
,
.
probe
=
rsnd_dvc_probe_gen2
,
...
...
@@ -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
;
}
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
,
const
struct
rsnd_of_data
*
of_data
,
struct
rsnd_priv
*
priv
)
...
...
@@ -250,6 +315,8 @@ int rsnd_dvc_probe(struct platform_device *pdev,
char
name
[
RSND_DVC_NAME_SIZE
];
int
i
,
nr
;
rsnd_of_parse_dvc
(
pdev
,
of_data
,
priv
);
nr
=
info
->
dvc_info_nr
;
if
(
!
nr
)
return
0
;
...
...
sound/soc/sh/rcar/gen.c
浏览文件 @
2fd53734
此差异已折叠。
点击以展开。
sound/soc/sh/rcar/rsnd.h
浏览文件 @
2fd53734
...
...
@@ -90,6 +90,7 @@ enum rsnd_reg {
RSND_REG_SHARE19
,
RSND_REG_SHARE20
,
RSND_REG_SHARE21
,
RSND_REG_SHARE22
,
RSND_REG_MAX
,
};
...
...
@@ -127,6 +128,7 @@ enum rsnd_reg {
#define RSND_REG_AUDIO_CLK_SEL2 RSND_REG_SHARE19
#define RSND_REG_CMD_CTRL RSND_REG_SHARE20
#define RSND_REG_CMDOUT_TIMSEL RSND_REG_SHARE21
#define RSND_REG_BUSIF_DALIGN RSND_REG_SHARE22
struct
rsnd_of_data
;
struct
rsnd_priv
;
...
...
@@ -156,12 +158,9 @@ u32 rsnd_get_adinr(struct rsnd_mod *mod);
*/
struct
rsnd_dma
{
struct
sh_dmae_slave
slave
;
struct
work_struct
work
;
struct
dma_chan
*
chan
;
enum
dma_data_direction
dir
;
int
submit_loop
;
int
offset
;
/* it cares A/B plane */
enum
dma_transfer_direction
dir
;
dma_addr_t
addr
;
};
void
rsnd_dma_start
(
struct
rsnd_dma
*
dma
);
...
...
@@ -185,6 +184,7 @@ enum rsnd_mod_type {
struct
rsnd_mod_ops
{
char
*
name
;
char
*
(
*
dma_name
)(
struct
rsnd_mod
*
mod
);
int
(
*
probe
)(
struct
rsnd_mod
*
mod
,
struct
rsnd_dai
*
rdai
);
int
(
*
remove
)(
struct
rsnd_mod
*
mod
,
...
...
@@ -224,6 +224,7 @@ void rsnd_mod_init(struct rsnd_priv *priv,
enum
rsnd_mod_type
type
,
int
id
);
char
*
rsnd_mod_name
(
struct
rsnd_mod
*
mod
);
char
*
rsnd_mod_dma_name
(
struct
rsnd_mod
*
mod
);
/*
* R-Car sound DAI
...
...
@@ -281,10 +282,9 @@ int rsnd_gen_probe(struct platform_device *pdev,
void
__iomem
*
rsnd_gen_reg_get
(
struct
rsnd_priv
*
priv
,
struct
rsnd_mod
*
mod
,
enum
rsnd_reg
reg
);
void
rsnd_gen_dma_addr
(
struct
rsnd_priv
*
priv
,
struct
rsnd_dma
*
dma
,
struct
dma_slave_config
*
cfg
,
int
is_play
,
int
slave_id
);
dma_addr_t
rsnd_gen_dma_addr
(
struct
rsnd_priv
*
priv
,
struct
rsnd_mod
*
mod
,
int
is_play
,
int
is_from
);
#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)
...
...
@@ -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
,
struct
rsnd_dai_stream
*
io
,
struct
snd_pcm_runtime
*
runtime
);
int
rsnd_src_ssi_mode_init
(
struct
rsnd_mod
*
ssi_mod
,
struct
rsnd_dai
*
rdai
);
int
rsnd_src_ssiu_start
(
struct
rsnd_mod
*
ssi_mod
,
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
,
struct
rsnd_dai
*
rdai
);
...
...
sound/soc/sh/rcar/src.c
浏览文件 @
2fd53734
...
...
@@ -106,18 +106,19 @@ struct rsnd_src {
/*
* Gen1/Gen2 common functions
*/
int
rsnd_src_ssi_mode_init
(
struct
rsnd_mod
*
ssi_mod
,
struct
rsnd_dai
*
rdai
)
int
rsnd_src_ssiu_start
(
struct
rsnd_mod
*
ssi_mod
,
struct
rsnd_dai
*
rdai
,
int
use_busif
)
{
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
);
/*
* SSI_MODE0
*/
rsnd_mod_bset
(
ssi_mod
,
SSI_MODE0
,
(
1
<<
ssi_id
),
src_mod
?
0
:
(
1
<<
ssi_id
)
);
!
use_busif
<<
ssi_id
);
/*
* SSI_MODE1
...
...
@@ -143,6 +144,46 @@ int rsnd_src_ssi_mode_init(struct rsnd_mod *ssi_mod,
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
;
}
...
...
@@ -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
,
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
;
/* 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
);
if
(
ret
<
0
)
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_BSDSR
,
0x01800000
);
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
);
break
;
}
rsnd_mod_write
(
mod
,
SRC_BSISR
,
0x00100060
);
return
0
;
...
...
@@ -554,7 +622,6 @@ static int rsnd_src_start_gen2(struct rsnd_mod *mod,
rsnd_dma_start
(
rsnd_mod_to_dma
(
&
src
->
mod
));
rsnd_mod_write
(
mod
,
SSI_CTRL
,
0x1
);
rsnd_mod_write
(
mod
,
SRC_CTRL
,
val
);
return
rsnd_src_start
(
mod
,
rdai
);
...
...
@@ -565,7 +632,6 @@ static int rsnd_src_stop_gen2(struct rsnd_mod *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_dma_stop
(
rsnd_mod_to_dma
(
&
src
->
mod
));
...
...
sound/soc/sh/rcar/ssi.c
浏览文件 @
2fd53734
...
...
@@ -90,6 +90,20 @@ struct rsnd_ssi {
#define rsnd_ssi_mode_flags(p) ((p)->info->flags)
#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
,
u32
bit
)
{
...
...
@@ -289,8 +303,6 @@ static int rsnd_ssi_init(struct rsnd_mod *mod,
ssi
->
cr_own
=
cr
;
ssi
->
err
=
-
1
;
/* ignore 1st error */
rsnd_src_ssi_mode_init
(
mod
,
rdai
);
return
0
;
}
...
...
@@ -389,6 +401,8 @@ static int rsnd_ssi_pio_start(struct rsnd_mod *mod,
/* enable PIO IRQ */
ssi
->
cr_etc
=
UIEN
|
OIEN
|
DIEN
;
rsnd_src_ssiu_start
(
mod
,
rdai
,
0
);
rsnd_src_enable_ssi_irq
(
mod
,
rdai
);
rsnd_ssi_hw_start
(
ssi
,
rdai
,
io
);
...
...
@@ -405,6 +419,8 @@ static int rsnd_ssi_pio_stop(struct rsnd_mod *mod,
rsnd_ssi_hw_stop
(
ssi
,
rdai
);
rsnd_src_ssiu_stop
(
mod
,
rdai
,
0
);
return
0
;
}
...
...
@@ -457,6 +473,8 @@ static int rsnd_ssi_dma_start(struct rsnd_mod *mod,
/* enable DMA transfer */
ssi
->
cr_etc
=
DMEN
;
rsnd_src_ssiu_start
(
mod
,
rdai
,
rsnd_ssi_use_busif
(
mod
));
rsnd_dma_start
(
dma
);
rsnd_ssi_hw_start
(
ssi
,
ssi
->
rdai
,
io
);
...
...
@@ -482,11 +500,19 @@ static int rsnd_ssi_dma_stop(struct rsnd_mod *mod,
rsnd_dma_stop
(
dma
);
rsnd_src_ssiu_stop
(
mod
,
rdai
,
1
);
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
=
{
.
name
=
SSI_NAME
,
.
dma_name
=
rsnd_ssi_dma_name
,
.
probe
=
rsnd_ssi_dma_probe
,
.
remove
=
rsnd_ssi_dma_remove
,
.
init
=
rsnd_ssi_init
,
...
...
@@ -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
)
?
0
:
1
;
if
(
of_get_property
(
np
,
"no-busif"
,
NULL
))
ssi_info
->
flags
|=
RSND_SSI_NO_BUSIF
;
}
rsnd_of_parse_ssi_end:
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录