Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
cloud-kernel
提交
954f497f
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看板
提交
954f497f
编写于
12月 10, 2012
作者:
M
Mark Brown
浏览文件
操作
浏览文件
下载
差异文件
Merge remote-tracking branch 'asoc/topic/fsi' into asoc-next
上级
1870975f
3449f5fa
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
487 addition
and
69 deletion
+487
-69
include/sound/sh_fsi.h
include/sound/sh_fsi.h
+6
-0
sound/soc/sh/fsi.c
sound/soc/sh/fsi.c
+481
-69
未找到文件。
include/sound/sh_fsi.h
浏览文件 @
954f497f
...
...
@@ -26,6 +26,7 @@
* A: inversion
* B: format mode
* C: chip specific
* D: clock selecter if master mode
*/
/* A: clock inversion */
...
...
@@ -44,6 +45,11 @@
#define SH_FSI_OPTION_MASK 0x00000F00
#define SH_FSI_ENABLE_STREAM_MODE (1 << 8)
/* for 16bit data */
/* D: clock selecter if master mode */
#define SH_FSI_CLK_MASK 0x0000F000
#define SH_FSI_CLK_EXTERNAL (0 << 12)
#define SH_FSI_CLK_CPG (1 << 12)
/* FSIxCK + FSI-DIV */
/*
* set_rate return value
*
...
...
sound/soc/sh/fsi.c
浏览文件 @
954f497f
...
...
@@ -22,6 +22,7 @@
#include <linux/module.h>
#include <linux/workqueue.h>
#include <sound/soc.h>
#include <sound/pcm_params.h>
#include <sound/sh_fsi.h>
/* PortA/PortB register */
...
...
@@ -188,6 +189,14 @@ typedef int (*set_rate_func)(struct device *dev, int rate, int enable);
* --> go to codecs
*/
/*
* FSI clock
*
* FSIxCLK [CPG] (ick) -------> |
* |-> FSI_DIV (div)-> FSI2
* FSIxCK [external] (xck) ---> |
*/
/*
* struct
*/
...
...
@@ -228,6 +237,20 @@ struct fsi_stream {
dma_addr_t
dma
;
};
struct
fsi_clk
{
/* see [FSI clock] */
struct
clk
*
own
;
struct
clk
*
xck
;
struct
clk
*
ick
;
struct
clk
*
div
;
int
(
*
set_rate
)(
struct
device
*
dev
,
struct
fsi_priv
*
fsi
,
unsigned
long
rate
);
unsigned
long
rate
;
unsigned
int
count
;
};
struct
fsi_priv
{
void
__iomem
*
base
;
struct
fsi_master
*
master
;
...
...
@@ -236,11 +259,17 @@ struct fsi_priv {
struct
fsi_stream
playback
;
struct
fsi_stream
capture
;
struct
fsi_clk
clock
;
u32
fmt
;
int
chan_num
:
16
;
int
clk_master
:
1
;
int
clk_cpg
:
1
;
int
spdif
:
1
;
int
enable_stream
:
1
;
int
bit_clk_inv
:
1
;
int
lr_clk_inv
:
1
;
long
rate
;
};
...
...
@@ -370,6 +399,11 @@ static int fsi_is_spdif(struct fsi_priv *fsi)
return
fsi
->
spdif
;
}
static
int
fsi_is_enable_stream
(
struct
fsi_priv
*
fsi
)
{
return
fsi
->
enable_stream
;
}
static
int
fsi_is_play
(
struct
snd_pcm_substream
*
substream
)
{
return
substream
->
stream
==
SNDRV_PCM_STREAM_PLAYBACK
;
...
...
@@ -717,14 +751,335 @@ static void fsi_spdif_clk_ctrl(struct fsi_priv *fsi, int enable)
/*
* clock function
*/
static
int
fsi_clk_init
(
struct
device
*
dev
,
struct
fsi_priv
*
fsi
,
int
xck
,
int
ick
,
int
div
,
int
(
*
set_rate
)(
struct
device
*
dev
,
struct
fsi_priv
*
fsi
,
unsigned
long
rate
))
{
struct
fsi_clk
*
clock
=
&
fsi
->
clock
;
int
is_porta
=
fsi_is_port_a
(
fsi
);
clock
->
xck
=
NULL
;
clock
->
ick
=
NULL
;
clock
->
div
=
NULL
;
clock
->
rate
=
0
;
clock
->
count
=
0
;
clock
->
set_rate
=
set_rate
;
clock
->
own
=
devm_clk_get
(
dev
,
NULL
);
if
(
IS_ERR
(
clock
->
own
))
return
-
EINVAL
;
/* external clock */
if
(
xck
)
{
clock
->
xck
=
devm_clk_get
(
dev
,
is_porta
?
"xcka"
:
"xckb"
);
if
(
IS_ERR
(
clock
->
xck
))
{
dev_err
(
dev
,
"can't get xck clock
\n
"
);
return
-
EINVAL
;
}
if
(
clock
->
xck
==
clock
->
own
)
{
dev_err
(
dev
,
"cpu doesn't support xck clock
\n
"
);
return
-
EINVAL
;
}
}
/* FSIACLK/FSIBCLK */
if
(
ick
)
{
clock
->
ick
=
devm_clk_get
(
dev
,
is_porta
?
"icka"
:
"ickb"
);
if
(
IS_ERR
(
clock
->
ick
))
{
dev_err
(
dev
,
"can't get ick clock
\n
"
);
return
-
EINVAL
;
}
if
(
clock
->
ick
==
clock
->
own
)
{
dev_err
(
dev
,
"cpu doesn't support ick clock
\n
"
);
return
-
EINVAL
;
}
}
/* FSI-DIV */
if
(
div
)
{
clock
->
div
=
devm_clk_get
(
dev
,
is_porta
?
"diva"
:
"divb"
);
if
(
IS_ERR
(
clock
->
div
))
{
dev_err
(
dev
,
"can't get div clock
\n
"
);
return
-
EINVAL
;
}
if
(
clock
->
div
==
clock
->
own
)
{
dev_err
(
dev
,
"cpu doens't support div clock
\n
"
);
return
-
EINVAL
;
}
}
return
0
;
}
#define fsi_clk_invalid(fsi) fsi_clk_valid(fsi, 0)
static
void
fsi_clk_valid
(
struct
fsi_priv
*
fsi
,
unsigned
long
rate
)
{
fsi
->
clock
.
rate
=
rate
;
}
static
int
fsi_clk_is_valid
(
struct
fsi_priv
*
fsi
)
{
return
fsi
->
clock
.
set_rate
&&
fsi
->
clock
.
rate
;
}
static
int
fsi_clk_enable
(
struct
device
*
dev
,
struct
fsi_priv
*
fsi
,
unsigned
long
rate
)
{
struct
fsi_clk
*
clock
=
&
fsi
->
clock
;
int
ret
=
-
EINVAL
;
if
(
!
fsi_clk_is_valid
(
fsi
))
return
ret
;
if
(
0
==
clock
->
count
)
{
ret
=
clock
->
set_rate
(
dev
,
fsi
,
rate
);
if
(
ret
<
0
)
{
fsi_clk_invalid
(
fsi
);
return
ret
;
}
if
(
clock
->
xck
)
clk_enable
(
clock
->
xck
);
if
(
clock
->
ick
)
clk_enable
(
clock
->
ick
);
if
(
clock
->
div
)
clk_enable
(
clock
->
div
);
clock
->
count
++
;
}
return
ret
;
}
static
int
fsi_clk_disable
(
struct
device
*
dev
,
struct
fsi_priv
*
fsi
)
{
struct
fsi_clk
*
clock
=
&
fsi
->
clock
;
if
(
!
fsi_clk_is_valid
(
fsi
))
return
-
EINVAL
;
if
(
1
==
clock
->
count
--
)
{
if
(
clock
->
xck
)
clk_disable
(
clock
->
xck
);
if
(
clock
->
ick
)
clk_disable
(
clock
->
ick
);
if
(
clock
->
div
)
clk_disable
(
clock
->
div
);
}
return
0
;
}
static
int
fsi_clk_set_ackbpf
(
struct
device
*
dev
,
struct
fsi_priv
*
fsi
,
int
ackmd
,
int
bpfmd
)
{
u32
data
=
0
;
/* check ackmd/bpfmd relationship */
if
(
bpfmd
>
ackmd
)
{
dev_err
(
dev
,
"unsupported rate (%d/%d)
\n
"
,
ackmd
,
bpfmd
);
return
-
EINVAL
;
}
/* ACKMD */
switch
(
ackmd
)
{
case
512
:
data
|=
(
0x0
<<
12
);
break
;
case
256
:
data
|=
(
0x1
<<
12
);
break
;
case
128
:
data
|=
(
0x2
<<
12
);
break
;
case
64
:
data
|=
(
0x3
<<
12
);
break
;
case
32
:
data
|=
(
0x4
<<
12
);
break
;
default:
dev_err
(
dev
,
"unsupported ackmd (%d)
\n
"
,
ackmd
);
return
-
EINVAL
;
}
/* BPFMD */
switch
(
bpfmd
)
{
case
32
:
data
|=
(
0x0
<<
8
);
break
;
case
64
:
data
|=
(
0x1
<<
8
);
break
;
case
128
:
data
|=
(
0x2
<<
8
);
break
;
case
256
:
data
|=
(
0x3
<<
8
);
break
;
case
512
:
data
|=
(
0x4
<<
8
);
break
;
case
16
:
data
|=
(
0x7
<<
8
);
break
;
default:
dev_err
(
dev
,
"unsupported bpfmd (%d)
\n
"
,
bpfmd
);
return
-
EINVAL
;
}
dev_dbg
(
dev
,
"ACKMD/BPFMD = %d/%d
\n
"
,
ackmd
,
bpfmd
);
fsi_reg_mask_set
(
fsi
,
CKG1
,
(
ACKMD_MASK
|
BPFMD_MASK
)
,
data
);
udelay
(
10
);
return
0
;
}
static
int
fsi_clk_set_rate_external
(
struct
device
*
dev
,
struct
fsi_priv
*
fsi
,
unsigned
long
rate
)
{
struct
clk
*
xck
=
fsi
->
clock
.
xck
;
struct
clk
*
ick
=
fsi
->
clock
.
ick
;
unsigned
long
xrate
;
int
ackmd
,
bpfmd
;
int
ret
=
0
;
/* check clock rate */
xrate
=
clk_get_rate
(
xck
);
if
(
xrate
%
rate
)
{
dev_err
(
dev
,
"unsupported clock rate
\n
"
);
return
-
EINVAL
;
}
clk_set_parent
(
ick
,
xck
);
clk_set_rate
(
ick
,
xrate
);
bpfmd
=
fsi
->
chan_num
*
32
;
ackmd
=
xrate
/
rate
;
dev_dbg
(
dev
,
"external/rate = %ld/%ld
\n
"
,
xrate
,
rate
);
ret
=
fsi_clk_set_ackbpf
(
dev
,
fsi
,
ackmd
,
bpfmd
);
if
(
ret
<
0
)
dev_err
(
dev
,
"%s failed"
,
__func__
);
return
ret
;
}
static
int
fsi_clk_set_rate_cpg
(
struct
device
*
dev
,
struct
fsi_priv
*
fsi
,
unsigned
long
rate
)
{
struct
clk
*
ick
=
fsi
->
clock
.
ick
;
struct
clk
*
div
=
fsi
->
clock
.
div
;
unsigned
long
target
=
0
;
/* 12288000 or 11289600 */
unsigned
long
actual
,
cout
;
unsigned
long
diff
,
min
;
unsigned
long
best_cout
,
best_act
;
int
adj
;
int
ackmd
,
bpfmd
;
int
ret
=
-
EINVAL
;
if
(
!
(
12288000
%
rate
))
target
=
12288000
;
if
(
!
(
11289600
%
rate
))
target
=
11289600
;
if
(
!
target
)
{
dev_err
(
dev
,
"unsupported rate
\n
"
);
return
ret
;
}
bpfmd
=
fsi
->
chan_num
*
32
;
ackmd
=
target
/
rate
;
ret
=
fsi_clk_set_ackbpf
(
dev
,
fsi
,
ackmd
,
bpfmd
);
if
(
ret
<
0
)
{
dev_err
(
dev
,
"%s failed"
,
__func__
);
return
ret
;
}
/*
* The clock flow is
*
* [CPG] = cout => [FSI_DIV] = audio => [FSI] => [codec]
*
* But, it needs to find best match of CPG and FSI_DIV
* combination, since it is difficult to generate correct
* frequency of audio clock from ick clock only.
* Because ick is created from its parent clock.
*
* target = rate x [512/256/128/64]fs
* cout = round(target x adjustment)
* actual = cout / adjustment (by FSI-DIV) ~= target
* audio = actual
*/
min
=
~
0
;
best_cout
=
0
;
best_act
=
0
;
for
(
adj
=
1
;
adj
<
0xffff
;
adj
++
)
{
cout
=
target
*
adj
;
if
(
cout
>
100000000
)
/* max clock = 100MHz */
break
;
/* cout/actual audio clock */
cout
=
clk_round_rate
(
ick
,
cout
);
actual
=
cout
/
adj
;
/* find best frequency */
diff
=
abs
(
actual
-
target
);
if
(
diff
<
min
)
{
min
=
diff
;
best_cout
=
cout
;
best_act
=
actual
;
}
}
ret
=
clk_set_rate
(
ick
,
best_cout
);
if
(
ret
<
0
)
{
dev_err
(
dev
,
"ick clock failed
\n
"
);
return
-
EIO
;
}
ret
=
clk_set_rate
(
div
,
clk_round_rate
(
div
,
best_act
));
if
(
ret
<
0
)
{
dev_err
(
dev
,
"div clock failed
\n
"
);
return
-
EIO
;
}
dev_dbg
(
dev
,
"ick/div = %ld/%ld
\n
"
,
clk_get_rate
(
ick
),
clk_get_rate
(
div
));
return
ret
;
}
static
int
fsi_set_master_clk
(
struct
device
*
dev
,
struct
fsi_priv
*
fsi
,
long
rate
,
int
enable
)
{
set_rate_func
set_rate
=
fsi_get_info_set_rate
(
fsi
);
int
ret
;
if
(
!
set_rate
)
return
0
;
/*
* CAUTION
*
* set_rate will be deleted
*/
if
(
!
set_rate
)
{
if
(
enable
)
return
fsi_clk_enable
(
dev
,
fsi
,
rate
);
else
return
fsi_clk_disable
(
dev
,
fsi
);
}
ret
=
set_rate
(
dev
,
rate
,
enable
);
if
(
ret
<
0
)
/* error */
...
...
@@ -792,10 +1147,9 @@ static int fsi_set_master_clk(struct device *dev, struct fsi_priv *fsi,
*/
static
void
fsi_pio_push16
(
struct
fsi_priv
*
fsi
,
u8
*
_buf
,
int
samples
)
{
u32
enable_stream
=
fsi_get_info_flags
(
fsi
)
&
SH_FSI_ENABLE_STREAM_MODE
;
int
i
;
if
(
enable_stream
)
{
if
(
fsi_is_enable_stream
(
fsi
)
)
{
/*
* stream mode
* see
...
...
@@ -953,8 +1307,6 @@ static void fsi_pio_start_stop(struct fsi_priv *fsi, struct fsi_stream *io,
static
int
fsi_pio_push_init
(
struct
fsi_priv
*
fsi
,
struct
fsi_stream
*
io
)
{
u32
enable_stream
=
fsi_get_info_flags
(
fsi
)
&
SH_FSI_ENABLE_STREAM_MODE
;
/*
* we can use 16bit stream mode
* when "playback" and "16bit data"
...
...
@@ -962,7 +1314,7 @@ static int fsi_pio_push_init(struct fsi_priv *fsi, struct fsi_stream *io)
* see
* fsi_pio_push16()
*/
if
(
enable_stream
)
if
(
fsi_is_enable_stream
(
fsi
)
)
io
->
bus_option
=
BUSOP_SET
(
24
,
PACKAGE_24BITBUS_BACK
)
|
BUSOP_SET
(
16
,
PACKAGE_16BITBUS_STREAM
);
else
...
...
@@ -1296,6 +1648,16 @@ static int fsi_hw_startup(struct fsi_priv *fsi,
/* clock inversion (CKG2) */
data
=
0
;
if
(
fsi
->
bit_clk_inv
)
data
|=
(
1
<<
0
);
if
(
fsi
->
lr_clk_inv
)
data
|=
(
1
<<
4
);
if
(
fsi_is_clk_master
(
fsi
))
data
<<=
8
;
/* FIXME
*
* SH_FSI_xxx_INV style will be removed
*/
if
(
SH_FSI_LRM_INV
&
flags
)
data
|=
1
<<
12
;
if
(
SH_FSI_BRM_INV
&
flags
)
...
...
@@ -1334,14 +1696,21 @@ static int fsi_hw_startup(struct fsi_priv *fsi,
/* fifo init */
fsi_fifo_init
(
fsi
,
io
,
dev
);
/* start master clock */
if
(
fsi_is_clk_master
(
fsi
))
return
fsi_set_master_clk
(
dev
,
fsi
,
fsi
->
rate
,
1
);
return
0
;
}
static
void
fsi_hw_shutdown
(
struct
fsi_priv
*
fsi
,
static
int
fsi_hw_shutdown
(
struct
fsi_priv
*
fsi
,
struct
device
*
dev
)
{
/* stop master clock */
if
(
fsi_is_clk_master
(
fsi
))
fsi_set_master_clk
(
dev
,
fsi
,
fsi
->
rate
,
0
);
return
fsi_set_master_clk
(
dev
,
fsi
,
fsi
->
rate
,
0
);
return
0
;
}
static
int
fsi_dai_startup
(
struct
snd_pcm_substream
*
substream
,
...
...
@@ -1349,6 +1718,7 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream,
{
struct
fsi_priv
*
fsi
=
fsi_get_priv
(
substream
);
fsi_clk_invalid
(
fsi
);
fsi
->
rate
=
0
;
return
0
;
...
...
@@ -1359,6 +1729,7 @@ static void fsi_dai_shutdown(struct snd_pcm_substream *substream,
{
struct
fsi_priv
*
fsi
=
fsi_get_priv
(
substream
);
fsi_clk_invalid
(
fsi
);
fsi
->
rate
=
0
;
}
...
...
@@ -1372,13 +1743,16 @@ static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd,
switch
(
cmd
)
{
case
SNDRV_PCM_TRIGGER_START
:
fsi_stream_init
(
fsi
,
io
,
substream
);
fsi_hw_startup
(
fsi
,
io
,
dai
->
dev
);
ret
=
fsi_stream_transfer
(
io
);
if
(
0
==
ret
)
if
(
!
ret
)
ret
=
fsi_hw_startup
(
fsi
,
io
,
dai
->
dev
);
if
(
!
ret
)
ret
=
fsi_stream_transfer
(
io
);
if
(
!
ret
)
fsi_stream_start
(
fsi
,
io
);
break
;
case
SNDRV_PCM_TRIGGER_STOP
:
fsi_hw_shutdown
(
fsi
,
dai
->
dev
);
if
(
!
ret
)
ret
=
fsi_hw_shutdown
(
fsi
,
dai
->
dev
);
fsi_stream_stop
(
fsi
,
io
);
fsi_stream_quit
(
fsi
,
io
);
break
;
...
...
@@ -1414,7 +1788,6 @@ static int fsi_set_fmt_spdif(struct fsi_priv *fsi)
fsi
->
fmt
=
CR_DTMD_SPDIF_PCM
|
CR_PCM
;
fsi
->
chan_num
=
2
;
fsi
->
spdif
=
1
;
return
0
;
}
...
...
@@ -1423,7 +1796,6 @@ static int fsi_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
{
struct
fsi_priv
*
fsi
=
fsi_get_priv_frm_dai
(
dai
);
set_rate_func
set_rate
=
fsi_get_info_set_rate
(
fsi
);
u32
flags
=
fsi_get_info_flags
(
fsi
);
int
ret
;
/* set master/slave audio interface */
...
...
@@ -1437,23 +1809,50 @@ static int fsi_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
return
-
EINVAL
;
}
if
(
fsi_is_clk_master
(
fsi
)
&&
!
set_rate
)
{
dev_err
(
dai
->
dev
,
"platform doesn't have set_rate
\n
"
);
return
-
EINVAL
;
}
/* set format */
switch
(
flags
&
SH_FSI_FMT_MASK
)
{
case
SH_FSI_FMT_DAI
:
ret
=
fsi_set_fmt_dai
(
fsi
,
fmt
&
SND_SOC_DAIFMT_FORMAT_MASK
);
/* set clock inversion */
switch
(
fmt
&
SND_SOC_DAIFMT_INV_MASK
)
{
case
SND_SOC_DAIFMT_NB_IF
:
fsi
->
bit_clk_inv
=
0
;
fsi
->
lr_clk_inv
=
1
;
break
;
case
SH_FSI_FMT_SPDIF
:
ret
=
fsi_set_fmt_spdif
(
fsi
);
case
SND_SOC_DAIFMT_IB_NF
:
fsi
->
bit_clk_inv
=
1
;
fsi
->
lr_clk_inv
=
0
;
break
;
case
SND_SOC_DAIFMT_IB_IF
:
fsi
->
bit_clk_inv
=
1
;
fsi
->
lr_clk_inv
=
1
;
break
;
case
SND_SOC_DAIFMT_NB_NF
:
default:
ret
=
-
EINVAL
;
fsi
->
bit_clk_inv
=
0
;
fsi
->
lr_clk_inv
=
0
;
break
;
}
if
(
fsi_is_clk_master
(
fsi
))
{
/*
* CAUTION
*
* set_rate will be deleted
*/
if
(
set_rate
)
dev_warn
(
dai
->
dev
,
"set_rate will be removed soon
\n
"
);
if
(
fsi
->
clk_cpg
)
fsi_clk_init
(
dai
->
dev
,
fsi
,
0
,
1
,
1
,
fsi_clk_set_rate_cpg
);
else
fsi_clk_init
(
dai
->
dev
,
fsi
,
1
,
1
,
0
,
fsi_clk_set_rate_external
);
}
/* set format */
if
(
fsi_is_spdif
(
fsi
))
ret
=
fsi_set_fmt_spdif
(
fsi
);
else
ret
=
fsi_set_fmt_dai
(
fsi
,
fmt
&
SND_SOC_DAIFMT_FORMAT_MASK
);
return
ret
;
}
...
...
@@ -1462,19 +1861,13 @@ static int fsi_dai_hw_params(struct snd_pcm_substream *substream,
struct
snd_soc_dai
*
dai
)
{
struct
fsi_priv
*
fsi
=
fsi_get_priv
(
substream
);
long
rate
=
params_rate
(
params
);
int
ret
;
if
(
!
fsi_is_clk_master
(
fsi
))
return
0
;
ret
=
fsi_set_master_clk
(
dai
->
dev
,
fsi
,
rate
,
1
);
if
(
ret
<
0
)
return
ret
;
fsi
->
rate
=
rate
;
if
(
fsi_is_clk_master
(
fsi
))
{
fsi
->
rate
=
params_rate
(
params
);
fsi_clk_valid
(
fsi
,
fsi
->
rate
);
}
return
ret
;
return
0
;
}
static
const
struct
snd_soc_dai_ops
fsi_dai_ops
=
{
...
...
@@ -1498,7 +1891,7 @@ static struct snd_pcm_hardware fsi_pcm_hardware = {
.
rates
=
FSI_RATES
,
.
rate_min
=
8000
,
.
rate_max
=
192000
,
.
channels_min
=
1
,
.
channels_min
=
2
,
.
channels_max
=
2
,
.
buffer_bytes_max
=
64
*
1024
,
.
period_bytes_min
=
32
,
...
...
@@ -1586,14 +1979,14 @@ static struct snd_soc_dai_driver fsi_soc_dai[] = {
.
playback
=
{
.
rates
=
FSI_RATES
,
.
formats
=
FSI_FMTS
,
.
channels_min
=
1
,
.
channels_max
=
8
,
.
channels_min
=
2
,
.
channels_max
=
2
,
},
.
capture
=
{
.
rates
=
FSI_RATES
,
.
formats
=
FSI_FMTS
,
.
channels_min
=
1
,
.
channels_max
=
8
,
.
channels_min
=
2
,
.
channels_max
=
2
,
},
.
ops
=
&
fsi_dai_ops
,
},
...
...
@@ -1602,14 +1995,14 @@ static struct snd_soc_dai_driver fsi_soc_dai[] = {
.
playback
=
{
.
rates
=
FSI_RATES
,
.
formats
=
FSI_FMTS
,
.
channels_min
=
1
,
.
channels_max
=
8
,
.
channels_min
=
2
,
.
channels_max
=
2
,
},
.
capture
=
{
.
rates
=
FSI_RATES
,
.
formats
=
FSI_FMTS
,
.
channels_min
=
1
,
.
channels_max
=
8
,
.
channels_min
=
2
,
.
channels_max
=
2
,
},
.
ops
=
&
fsi_dai_ops
,
},
...
...
@@ -1624,15 +2017,29 @@ static struct snd_soc_platform_driver fsi_soc_platform = {
/*
* platform function
*/
static
void
fsi_handler_init
(
struct
fsi_priv
*
fsi
)
static
void
fsi_port_info_init
(
struct
fsi_priv
*
fsi
,
struct
sh_fsi_port_info
*
info
)
{
if
(
info
->
flags
&
SH_FSI_FMT_SPDIF
)
fsi
->
spdif
=
1
;
if
(
info
->
flags
&
SH_FSI_CLK_CPG
)
fsi
->
clk_cpg
=
1
;
if
(
info
->
flags
&
SH_FSI_ENABLE_STREAM_MODE
)
fsi
->
enable_stream
=
1
;
}
static
void
fsi_handler_init
(
struct
fsi_priv
*
fsi
,
struct
sh_fsi_port_info
*
info
)
{
fsi
->
playback
.
handler
=
&
fsi_pio_push_handler
;
/* default PIO */
fsi
->
playback
.
priv
=
fsi
;
fsi
->
capture
.
handler
=
&
fsi_pio_pop_handler
;
/* default PIO */
fsi
->
capture
.
priv
=
fsi
;
if
(
fsi
->
info
->
tx_id
)
{
fsi
->
playback
.
slave
.
shdma_slave
.
slave_id
=
fsi
->
info
->
tx_id
;
if
(
info
->
tx_id
)
{
fsi
->
playback
.
slave
.
shdma_slave
.
slave_id
=
info
->
tx_id
;
fsi
->
playback
.
handler
=
&
fsi_dma_push_handler
;
}
}
...
...
@@ -1642,10 +2049,16 @@ static int fsi_probe(struct platform_device *pdev)
struct
fsi_master
*
master
;
const
struct
platform_device_id
*
id_entry
;
struct
sh_fsi_platform_info
*
info
=
pdev
->
dev
.
platform_data
;
struct
sh_fsi_port_info
nul_info
,
*
pinfo
;
struct
fsi_priv
*
fsi
;
struct
resource
*
res
;
unsigned
int
irq
;
int
ret
;
nul_info
.
flags
=
0
;
nul_info
.
tx_id
=
0
;
nul_info
.
rx_id
=
0
;
id_entry
=
pdev
->
id_entry
;
if
(
!
id_entry
)
{
dev_err
(
&
pdev
->
dev
,
"unknown fsi device
\n
"
);
...
...
@@ -1678,22 +2091,28 @@ static int fsi_probe(struct platform_device *pdev)
spin_lock_init
(
&
master
->
lock
);
/* FSI A setting */
master
->
fsia
.
base
=
master
->
base
;
master
->
fsia
.
master
=
master
;
master
->
fsia
.
info
=
&
info
->
port_a
;
fsi_handler_init
(
&
master
->
fsia
);
ret
=
fsi_stream_probe
(
&
master
->
fsia
,
&
pdev
->
dev
);
pinfo
=
(
info
)
?
&
info
->
port_a
:
&
nul_info
;
fsi
=
&
master
->
fsia
;
fsi
->
base
=
master
->
base
;
fsi
->
master
=
master
;
fsi
->
info
=
pinfo
;
fsi_port_info_init
(
fsi
,
pinfo
);
fsi_handler_init
(
fsi
,
pinfo
);
ret
=
fsi_stream_probe
(
fsi
,
&
pdev
->
dev
);
if
(
ret
<
0
)
{
dev_err
(
&
pdev
->
dev
,
"FSIA stream probe failed
\n
"
);
return
ret
;
}
/* FSI B setting */
master
->
fsib
.
base
=
master
->
base
+
0x40
;
master
->
fsib
.
master
=
master
;
master
->
fsib
.
info
=
&
info
->
port_b
;
fsi_handler_init
(
&
master
->
fsib
);
ret
=
fsi_stream_probe
(
&
master
->
fsib
,
&
pdev
->
dev
);
pinfo
=
(
info
)
?
&
info
->
port_b
:
&
nul_info
;
fsi
=
&
master
->
fsib
;
fsi
->
base
=
master
->
base
+
0x40
;
fsi
->
master
=
master
;
fsi
->
info
=
pinfo
;
fsi_port_info_init
(
fsi
,
pinfo
);
fsi_handler_init
(
fsi
,
pinfo
);
ret
=
fsi_stream_probe
(
fsi
,
&
pdev
->
dev
);
if
(
ret
<
0
)
{
dev_err
(
&
pdev
->
dev
,
"FSIB stream probe failed
\n
"
);
goto
exit_fsia
;
...
...
@@ -1702,7 +2121,7 @@ static int fsi_probe(struct platform_device *pdev)
pm_runtime_enable
(
&
pdev
->
dev
);
dev_set_drvdata
(
&
pdev
->
dev
,
master
);
ret
=
request_irq
(
irq
,
&
fsi_interrupt
,
0
,
ret
=
devm_request_irq
(
&
pdev
->
dev
,
irq
,
&
fsi_interrupt
,
0
,
id_entry
->
name
,
master
);
if
(
ret
)
{
dev_err
(
&
pdev
->
dev
,
"irq request err
\n
"
);
...
...
@@ -1712,7 +2131,7 @@ static int fsi_probe(struct platform_device *pdev)
ret
=
snd_soc_register_platform
(
&
pdev
->
dev
,
&
fsi_soc_platform
);
if
(
ret
<
0
)
{
dev_err
(
&
pdev
->
dev
,
"cannot snd soc register
\n
"
);
goto
exit_f
ree_irq
;
goto
exit_f
sib
;
}
ret
=
snd_soc_register_dais
(
&
pdev
->
dev
,
fsi_soc_dai
,
...
...
@@ -1726,8 +2145,6 @@ static int fsi_probe(struct platform_device *pdev)
exit_snd_soc:
snd_soc_unregister_platform
(
&
pdev
->
dev
);
exit_free_irq:
free_irq
(
irq
,
master
);
exit_fsib:
pm_runtime_disable
(
&
pdev
->
dev
);
fsi_stream_remove
(
&
master
->
fsib
);
...
...
@@ -1743,7 +2160,6 @@ static int fsi_remove(struct platform_device *pdev)
master
=
dev_get_drvdata
(
&
pdev
->
dev
);
free_irq
(
master
->
irq
,
master
);
pm_runtime_disable
(
&
pdev
->
dev
);
snd_soc_unregister_dais
(
&
pdev
->
dev
,
ARRAY_SIZE
(
fsi_soc_dai
));
...
...
@@ -1774,10 +2190,6 @@ static void __fsi_resume(struct fsi_priv *fsi,
return
;
fsi_hw_startup
(
fsi
,
io
,
dev
);
if
(
fsi_is_clk_master
(
fsi
)
&&
fsi
->
rate
)
fsi_set_master_clk
(
dev
,
fsi
,
fsi
->
rate
,
1
);
fsi_stream_start
(
fsi
,
io
);
}
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录