Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
cloud-kernel
提交
fbc6c4ee
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看板
提交
fbc6c4ee
编写于
6月 30, 2013
作者:
M
Mark Brown
浏览文件
操作
浏览文件
下载
差异文件
Merge remote-tracking branch 'asoc/topic/adsp' into asoc-next
上级
44947837
0c2e3f34
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
455 addition
and
7 deletion
+455
-7
sound/soc/codecs/wm_adsp.c
sound/soc/codecs/wm_adsp.c
+452
-7
sound/soc/codecs/wm_adsp.h
sound/soc/codecs/wm_adsp.h
+3
-0
未找到文件。
sound/soc/codecs/wm_adsp.c
浏览文件 @
fbc6c4ee
...
...
@@ -21,6 +21,7 @@
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
#include <linux/workqueue.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
...
...
@@ -215,6 +216,36 @@ static struct {
[
WM_ADSP_FW_RX_ANC
]
=
{
.
file
=
"rx-anc"
},
};
struct
wm_coeff_ctl_ops
{
int
(
*
xget
)(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_value
*
ucontrol
);
int
(
*
xput
)(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_value
*
ucontrol
);
int
(
*
xinfo
)(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_info
*
uinfo
);
};
struct
wm_coeff
{
struct
device
*
dev
;
struct
list_head
ctl_list
;
struct
regmap
*
regmap
;
};
struct
wm_coeff_ctl
{
const
char
*
name
;
struct
snd_card
*
card
;
struct
wm_adsp_alg_region
region
;
struct
wm_coeff_ctl_ops
ops
;
struct
wm_adsp
*
adsp
;
void
*
private
;
unsigned
int
enabled
:
1
;
struct
list_head
list
;
void
*
cache
;
size_t
len
;
unsigned
int
set
:
1
;
struct
snd_kcontrol
*
kcontrol
;
};
static
int
wm_adsp_fw_get
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_value
*
ucontrol
)
{
...
...
@@ -334,6 +365,181 @@ static unsigned int wm_adsp_region_to_reg(struct wm_adsp_region const *region,
}
}
static
int
wm_coeff_info
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_info
*
uinfo
)
{
struct
wm_coeff_ctl
*
ctl
=
(
struct
wm_coeff_ctl
*
)
kcontrol
->
private_value
;
uinfo
->
type
=
SNDRV_CTL_ELEM_TYPE_BYTES
;
uinfo
->
count
=
ctl
->
len
;
return
0
;
}
static
int
wm_coeff_write_control
(
struct
snd_kcontrol
*
kcontrol
,
const
void
*
buf
,
size_t
len
)
{
struct
wm_coeff
*
wm_coeff
=
snd_kcontrol_chip
(
kcontrol
);
struct
wm_coeff_ctl
*
ctl
=
(
struct
wm_coeff_ctl
*
)
kcontrol
->
private_value
;
struct
wm_adsp_alg_region
*
region
=
&
ctl
->
region
;
const
struct
wm_adsp_region
*
mem
;
struct
wm_adsp
*
adsp
=
ctl
->
adsp
;
void
*
scratch
;
int
ret
;
unsigned
int
reg
;
mem
=
wm_adsp_find_region
(
adsp
,
region
->
type
);
if
(
!
mem
)
{
adsp_err
(
adsp
,
"No base for region %x
\n
"
,
region
->
type
);
return
-
EINVAL
;
}
reg
=
ctl
->
region
.
base
;
reg
=
wm_adsp_region_to_reg
(
mem
,
reg
);
scratch
=
kmemdup
(
buf
,
ctl
->
len
,
GFP_KERNEL
|
GFP_DMA
);
if
(
!
scratch
)
return
-
ENOMEM
;
ret
=
regmap_raw_write
(
wm_coeff
->
regmap
,
reg
,
scratch
,
ctl
->
len
);
if
(
ret
)
{
adsp_err
(
adsp
,
"Failed to write %zu bytes to %x
\n
"
,
ctl
->
len
,
reg
);
kfree
(
scratch
);
return
ret
;
}
kfree
(
scratch
);
return
0
;
}
static
int
wm_coeff_put
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_value
*
ucontrol
)
{
struct
wm_coeff_ctl
*
ctl
=
(
struct
wm_coeff_ctl
*
)
kcontrol
->
private_value
;
char
*
p
=
ucontrol
->
value
.
bytes
.
data
;
memcpy
(
ctl
->
cache
,
p
,
ctl
->
len
);
if
(
!
ctl
->
enabled
)
{
ctl
->
set
=
1
;
return
0
;
}
return
wm_coeff_write_control
(
kcontrol
,
p
,
ctl
->
len
);
}
static
int
wm_coeff_read_control
(
struct
snd_kcontrol
*
kcontrol
,
void
*
buf
,
size_t
len
)
{
struct
wm_coeff
*
wm_coeff
=
snd_kcontrol_chip
(
kcontrol
);
struct
wm_coeff_ctl
*
ctl
=
(
struct
wm_coeff_ctl
*
)
kcontrol
->
private_value
;
struct
wm_adsp_alg_region
*
region
=
&
ctl
->
region
;
const
struct
wm_adsp_region
*
mem
;
struct
wm_adsp
*
adsp
=
ctl
->
adsp
;
void
*
scratch
;
int
ret
;
unsigned
int
reg
;
mem
=
wm_adsp_find_region
(
adsp
,
region
->
type
);
if
(
!
mem
)
{
adsp_err
(
adsp
,
"No base for region %x
\n
"
,
region
->
type
);
return
-
EINVAL
;
}
reg
=
ctl
->
region
.
base
;
reg
=
wm_adsp_region_to_reg
(
mem
,
reg
);
scratch
=
kmalloc
(
ctl
->
len
,
GFP_KERNEL
|
GFP_DMA
);
if
(
!
scratch
)
return
-
ENOMEM
;
ret
=
regmap_raw_read
(
wm_coeff
->
regmap
,
reg
,
scratch
,
ctl
->
len
);
if
(
ret
)
{
adsp_err
(
adsp
,
"Failed to read %zu bytes from %x
\n
"
,
ctl
->
len
,
reg
);
kfree
(
scratch
);
return
ret
;
}
memcpy
(
buf
,
scratch
,
ctl
->
len
);
kfree
(
scratch
);
return
0
;
}
static
int
wm_coeff_get
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_value
*
ucontrol
)
{
struct
wm_coeff_ctl
*
ctl
=
(
struct
wm_coeff_ctl
*
)
kcontrol
->
private_value
;
char
*
p
=
ucontrol
->
value
.
bytes
.
data
;
memcpy
(
p
,
ctl
->
cache
,
ctl
->
len
);
return
0
;
}
static
int
wm_coeff_add_kcontrol
(
struct
wm_coeff
*
wm_coeff
,
struct
wm_coeff_ctl
*
ctl
,
const
struct
snd_kcontrol_new
*
kctl
)
{
int
ret
;
struct
snd_kcontrol
*
kcontrol
;
kcontrol
=
snd_ctl_new1
(
kctl
,
wm_coeff
);
ret
=
snd_ctl_add
(
ctl
->
card
,
kcontrol
);
if
(
ret
<
0
)
{
dev_err
(
wm_coeff
->
dev
,
"Failed to add %s: %d
\n
"
,
kctl
->
name
,
ret
);
return
ret
;
}
ctl
->
kcontrol
=
kcontrol
;
return
0
;
}
struct
wmfw_ctl_work
{
struct
wm_coeff
*
wm_coeff
;
struct
wm_coeff_ctl
*
ctl
;
struct
work_struct
work
;
};
static
int
wmfw_add_ctl
(
struct
wm_coeff
*
wm_coeff
,
struct
wm_coeff_ctl
*
ctl
)
{
struct
snd_kcontrol_new
*
kcontrol
;
int
ret
;
if
(
!
wm_coeff
||
!
ctl
||
!
ctl
->
name
||
!
ctl
->
card
)
return
-
EINVAL
;
kcontrol
=
kzalloc
(
sizeof
(
*
kcontrol
),
GFP_KERNEL
);
if
(
!
kcontrol
)
return
-
ENOMEM
;
kcontrol
->
iface
=
SNDRV_CTL_ELEM_IFACE_MIXER
;
kcontrol
->
name
=
ctl
->
name
;
kcontrol
->
info
=
wm_coeff_info
;
kcontrol
->
get
=
wm_coeff_get
;
kcontrol
->
put
=
wm_coeff_put
;
kcontrol
->
private_value
=
(
unsigned
long
)
ctl
;
ret
=
wm_coeff_add_kcontrol
(
wm_coeff
,
ctl
,
kcontrol
);
if
(
ret
<
0
)
goto
err_kcontrol
;
kfree
(
kcontrol
);
list_add
(
&
ctl
->
list
,
&
wm_coeff
->
ctl_list
);
return
0
;
err_kcontrol:
kfree
(
kcontrol
);
return
ret
;
}
static
int
wm_adsp_load
(
struct
wm_adsp
*
dsp
)
{
LIST_HEAD
(
buf_list
);
...
...
@@ -547,7 +753,157 @@ static int wm_adsp_load(struct wm_adsp *dsp)
return
ret
;
}
static
int
wm_adsp_setup_algs
(
struct
wm_adsp
*
dsp
)
static
int
wm_coeff_init_control_caches
(
struct
wm_coeff
*
wm_coeff
)
{
struct
wm_coeff_ctl
*
ctl
;
int
ret
;
list_for_each_entry
(
ctl
,
&
wm_coeff
->
ctl_list
,
list
)
{
if
(
!
ctl
->
enabled
||
ctl
->
set
)
continue
;
ret
=
wm_coeff_read_control
(
ctl
->
kcontrol
,
ctl
->
cache
,
ctl
->
len
);
if
(
ret
<
0
)
return
ret
;
}
return
0
;
}
static
int
wm_coeff_sync_controls
(
struct
wm_coeff
*
wm_coeff
)
{
struct
wm_coeff_ctl
*
ctl
;
int
ret
;
list_for_each_entry
(
ctl
,
&
wm_coeff
->
ctl_list
,
list
)
{
if
(
!
ctl
->
enabled
)
continue
;
if
(
ctl
->
set
)
{
ret
=
wm_coeff_write_control
(
ctl
->
kcontrol
,
ctl
->
cache
,
ctl
->
len
);
if
(
ret
<
0
)
return
ret
;
}
}
return
0
;
}
static
void
wm_adsp_ctl_work
(
struct
work_struct
*
work
)
{
struct
wmfw_ctl_work
*
ctl_work
=
container_of
(
work
,
struct
wmfw_ctl_work
,
work
);
wmfw_add_ctl
(
ctl_work
->
wm_coeff
,
ctl_work
->
ctl
);
kfree
(
ctl_work
);
}
static
int
wm_adsp_create_control
(
struct
snd_soc_codec
*
codec
,
const
struct
wm_adsp_alg_region
*
region
)
{
struct
wm_adsp
*
dsp
=
snd_soc_codec_get_drvdata
(
codec
);
struct
wm_coeff_ctl
*
ctl
;
struct
wmfw_ctl_work
*
ctl_work
;
char
*
name
;
char
*
region_name
;
int
ret
;
name
=
kmalloc
(
PAGE_SIZE
,
GFP_KERNEL
);
if
(
!
name
)
return
-
ENOMEM
;
switch
(
region
->
type
)
{
case
WMFW_ADSP1_PM
:
region_name
=
"PM"
;
break
;
case
WMFW_ADSP1_DM
:
region_name
=
"DM"
;
break
;
case
WMFW_ADSP2_XM
:
region_name
=
"XM"
;
break
;
case
WMFW_ADSP2_YM
:
region_name
=
"YM"
;
break
;
case
WMFW_ADSP1_ZM
:
region_name
=
"ZM"
;
break
;
default:
ret
=
-
EINVAL
;
goto
err_name
;
}
snprintf
(
name
,
PAGE_SIZE
,
"DSP%d %s %x"
,
dsp
->
num
,
region_name
,
region
->
alg
);
list_for_each_entry
(
ctl
,
&
dsp
->
wm_coeff
->
ctl_list
,
list
)
{
if
(
!
strcmp
(
ctl
->
name
,
name
))
{
if
(
!
ctl
->
enabled
)
ctl
->
enabled
=
1
;
goto
found
;
}
}
ctl
=
kzalloc
(
sizeof
(
*
ctl
),
GFP_KERNEL
);
if
(
!
ctl
)
{
ret
=
-
ENOMEM
;
goto
err_name
;
}
ctl
->
region
=
*
region
;
ctl
->
name
=
kmemdup
(
name
,
strlen
(
name
)
+
1
,
GFP_KERNEL
);
if
(
!
ctl
->
name
)
{
ret
=
-
ENOMEM
;
goto
err_ctl
;
}
ctl
->
enabled
=
1
;
ctl
->
set
=
0
;
ctl
->
ops
.
xget
=
wm_coeff_get
;
ctl
->
ops
.
xput
=
wm_coeff_put
;
ctl
->
card
=
codec
->
card
->
snd_card
;
ctl
->
adsp
=
dsp
;
ctl
->
len
=
region
->
len
;
ctl
->
cache
=
kzalloc
(
ctl
->
len
,
GFP_KERNEL
);
if
(
!
ctl
->
cache
)
{
ret
=
-
ENOMEM
;
goto
err_ctl_name
;
}
ctl_work
=
kzalloc
(
sizeof
(
*
ctl_work
),
GFP_KERNEL
);
if
(
!
ctl_work
)
{
ret
=
-
ENOMEM
;
goto
err_ctl_cache
;
}
ctl_work
->
wm_coeff
=
dsp
->
wm_coeff
;
ctl_work
->
ctl
=
ctl
;
INIT_WORK
(
&
ctl_work
->
work
,
wm_adsp_ctl_work
);
schedule_work
(
&
ctl_work
->
work
);
found:
kfree
(
name
);
return
0
;
err_ctl_cache:
kfree
(
ctl
->
cache
);
err_ctl_name:
kfree
(
ctl
->
name
);
err_ctl:
kfree
(
ctl
);
err_name:
kfree
(
name
);
return
ret
;
}
static
int
wm_adsp_setup_algs
(
struct
wm_adsp
*
dsp
,
struct
snd_soc_codec
*
codec
)
{
struct
regmap
*
regmap
=
dsp
->
regmap
;
struct
wmfw_adsp1_id_hdr
adsp1_id
;
...
...
@@ -730,7 +1086,16 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp)
region
->
type
=
WMFW_ADSP1_DM
;
region
->
alg
=
be32_to_cpu
(
adsp1_alg
[
i
].
alg
.
id
);
region
->
base
=
be32_to_cpu
(
adsp1_alg
[
i
].
dm
);
region
->
len
=
0
;
list_add_tail
(
&
region
->
list
,
&
dsp
->
alg_regions
);
if
(
i
+
1
<
algs
)
{
region
->
len
=
be32_to_cpu
(
adsp1_alg
[
i
+
1
].
dm
);
region
->
len
-=
be32_to_cpu
(
adsp1_alg
[
i
].
dm
);
wm_adsp_create_control
(
codec
,
region
);
}
else
{
adsp_warn
(
dsp
,
"Missing length info for region DM with ID %x
\n
"
,
be32_to_cpu
(
adsp1_alg
[
i
].
alg
.
id
));
}
region
=
kzalloc
(
sizeof
(
*
region
),
GFP_KERNEL
);
if
(
!
region
)
...
...
@@ -738,7 +1103,16 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp)
region
->
type
=
WMFW_ADSP1_ZM
;
region
->
alg
=
be32_to_cpu
(
adsp1_alg
[
i
].
alg
.
id
);
region
->
base
=
be32_to_cpu
(
adsp1_alg
[
i
].
zm
);
region
->
len
=
0
;
list_add_tail
(
&
region
->
list
,
&
dsp
->
alg_regions
);
if
(
i
+
1
<
algs
)
{
region
->
len
=
be32_to_cpu
(
adsp1_alg
[
i
+
1
].
zm
);
region
->
len
-=
be32_to_cpu
(
adsp1_alg
[
i
].
zm
);
wm_adsp_create_control
(
codec
,
region
);
}
else
{
adsp_warn
(
dsp
,
"Missing length info for region ZM with ID %x
\n
"
,
be32_to_cpu
(
adsp1_alg
[
i
].
alg
.
id
));
}
break
;
case
WMFW_ADSP2
:
...
...
@@ -758,7 +1132,16 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp)
region
->
type
=
WMFW_ADSP2_XM
;
region
->
alg
=
be32_to_cpu
(
adsp2_alg
[
i
].
alg
.
id
);
region
->
base
=
be32_to_cpu
(
adsp2_alg
[
i
].
xm
);
region
->
len
=
0
;
list_add_tail
(
&
region
->
list
,
&
dsp
->
alg_regions
);
if
(
i
+
1
<
algs
)
{
region
->
len
=
be32_to_cpu
(
adsp2_alg
[
i
+
1
].
xm
);
region
->
len
-=
be32_to_cpu
(
adsp2_alg
[
i
].
xm
);
wm_adsp_create_control
(
codec
,
region
);
}
else
{
adsp_warn
(
dsp
,
"Missing length info for region XM with ID %x
\n
"
,
be32_to_cpu
(
adsp2_alg
[
i
].
alg
.
id
));
}
region
=
kzalloc
(
sizeof
(
*
region
),
GFP_KERNEL
);
if
(
!
region
)
...
...
@@ -766,7 +1149,16 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp)
region
->
type
=
WMFW_ADSP2_YM
;
region
->
alg
=
be32_to_cpu
(
adsp2_alg
[
i
].
alg
.
id
);
region
->
base
=
be32_to_cpu
(
adsp2_alg
[
i
].
ym
);
region
->
len
=
0
;
list_add_tail
(
&
region
->
list
,
&
dsp
->
alg_regions
);
if
(
i
+
1
<
algs
)
{
region
->
len
=
be32_to_cpu
(
adsp2_alg
[
i
+
1
].
ym
);
region
->
len
-=
be32_to_cpu
(
adsp2_alg
[
i
].
ym
);
wm_adsp_create_control
(
codec
,
region
);
}
else
{
adsp_warn
(
dsp
,
"Missing length info for region YM with ID %x
\n
"
,
be32_to_cpu
(
adsp2_alg
[
i
].
alg
.
id
));
}
region
=
kzalloc
(
sizeof
(
*
region
),
GFP_KERNEL
);
if
(
!
region
)
...
...
@@ -774,7 +1166,16 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp)
region
->
type
=
WMFW_ADSP2_ZM
;
region
->
alg
=
be32_to_cpu
(
adsp2_alg
[
i
].
alg
.
id
);
region
->
base
=
be32_to_cpu
(
adsp2_alg
[
i
].
zm
);
region
->
len
=
0
;
list_add_tail
(
&
region
->
list
,
&
dsp
->
alg_regions
);
if
(
i
+
1
<
algs
)
{
region
->
len
=
be32_to_cpu
(
adsp2_alg
[
i
+
1
].
zm
);
region
->
len
-=
be32_to_cpu
(
adsp2_alg
[
i
].
zm
);
wm_adsp_create_control
(
codec
,
region
);
}
else
{
adsp_warn
(
dsp
,
"Missing length info for region ZM with ID %x
\n
"
,
be32_to_cpu
(
adsp2_alg
[
i
].
alg
.
id
));
}
break
;
}
}
...
...
@@ -986,6 +1387,7 @@ int wm_adsp1_event(struct snd_soc_dapm_widget *w,
struct
snd_soc_codec
*
codec
=
w
->
codec
;
struct
wm_adsp
*
dsps
=
snd_soc_codec_get_drvdata
(
codec
);
struct
wm_adsp
*
dsp
=
&
dsps
[
w
->
shift
];
struct
wm_coeff_ctl
*
ctl
;
int
ret
;
int
val
;
...
...
@@ -1023,7 +1425,7 @@ int wm_adsp1_event(struct snd_soc_dapm_widget *w,
if
(
ret
!=
0
)
goto
err
;
ret
=
wm_adsp_setup_algs
(
dsp
);
ret
=
wm_adsp_setup_algs
(
dsp
,
codec
);
if
(
ret
!=
0
)
goto
err
;
...
...
@@ -1031,6 +1433,16 @@ int wm_adsp1_event(struct snd_soc_dapm_widget *w,
if
(
ret
!=
0
)
goto
err
;
/* Initialize caches for enabled and unset controls */
ret
=
wm_coeff_init_control_caches
(
dsp
->
wm_coeff
);
if
(
ret
!=
0
)
goto
err
;
/* Sync set controls */
ret
=
wm_coeff_sync_controls
(
dsp
->
wm_coeff
);
if
(
ret
!=
0
)
goto
err
;
/* Start the core running */
regmap_update_bits
(
dsp
->
regmap
,
dsp
->
base
+
ADSP1_CONTROL_30
,
ADSP1_CORE_ENA
|
ADSP1_START
,
...
...
@@ -1047,6 +1459,11 @@ int wm_adsp1_event(struct snd_soc_dapm_widget *w,
regmap_update_bits
(
dsp
->
regmap
,
dsp
->
base
+
ADSP1_CONTROL_30
,
ADSP1_SYS_ENA
,
0
);
list_for_each_entry
(
ctl
,
&
dsp
->
wm_coeff
->
ctl_list
,
list
)
{
ctl
->
enabled
=
0
;
}
break
;
default:
...
...
@@ -1099,6 +1516,7 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w,
struct
wm_adsp
*
dsps
=
snd_soc_codec_get_drvdata
(
codec
);
struct
wm_adsp
*
dsp
=
&
dsps
[
w
->
shift
];
struct
wm_adsp_alg_region
*
alg_region
;
struct
wm_coeff_ctl
*
ctl
;
unsigned
int
val
;
int
ret
;
...
...
@@ -1164,7 +1582,7 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w,
if
(
ret
!=
0
)
goto
err
;
ret
=
wm_adsp_setup_algs
(
dsp
);
ret
=
wm_adsp_setup_algs
(
dsp
,
codec
);
if
(
ret
!=
0
)
goto
err
;
...
...
@@ -1172,6 +1590,16 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w,
if
(
ret
!=
0
)
goto
err
;
/* Initialize caches for enabled and unset controls */
ret
=
wm_coeff_init_control_caches
(
dsp
->
wm_coeff
);
if
(
ret
!=
0
)
goto
err
;
/* Sync set controls */
ret
=
wm_coeff_sync_controls
(
dsp
->
wm_coeff
);
if
(
ret
!=
0
)
goto
err
;
ret
=
regmap_update_bits
(
dsp
->
regmap
,
dsp
->
base
+
ADSP2_CONTROL
,
ADSP2_CORE_ENA
|
ADSP2_START
,
...
...
@@ -1209,6 +1637,11 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w,
ret
);
}
list_for_each_entry
(
ctl
,
&
dsp
->
wm_coeff
->
ctl_list
,
list
)
{
ctl
->
enabled
=
0
;
}
while
(
!
list_empty
(
&
dsp
->
alg_regions
))
{
alg_region
=
list_first_entry
(
&
dsp
->
alg_regions
,
struct
wm_adsp_alg_region
,
...
...
@@ -1247,36 +1680,48 @@ int wm_adsp2_init(struct wm_adsp *adsp, bool dvfs)
INIT_LIST_HEAD
(
&
adsp
->
alg_regions
);
adsp
->
wm_coeff
=
kzalloc
(
sizeof
(
*
adsp
->
wm_coeff
),
GFP_KERNEL
);
if
(
!
adsp
->
wm_coeff
)
return
-
ENOMEM
;
adsp
->
wm_coeff
->
regmap
=
adsp
->
regmap
;
adsp
->
wm_coeff
->
dev
=
adsp
->
dev
;
INIT_LIST_HEAD
(
&
adsp
->
wm_coeff
->
ctl_list
);
if
(
dvfs
)
{
adsp
->
dvfs
=
devm_regulator_get
(
adsp
->
dev
,
"DCVDD"
);
if
(
IS_ERR
(
adsp
->
dvfs
))
{
ret
=
PTR_ERR
(
adsp
->
dvfs
);
dev_err
(
adsp
->
dev
,
"Failed to get DCVDD: %d
\n
"
,
ret
);
return
ret
;
goto
out_coeff
;
}
ret
=
regulator_enable
(
adsp
->
dvfs
);
if
(
ret
!=
0
)
{
dev_err
(
adsp
->
dev
,
"Failed to enable DCVDD: %d
\n
"
,
ret
);
return
ret
;
goto
out_coeff
;
}
ret
=
regulator_set_voltage
(
adsp
->
dvfs
,
1200000
,
1800000
);
if
(
ret
!=
0
)
{
dev_err
(
adsp
->
dev
,
"Failed to initialise DVFS: %d
\n
"
,
ret
);
return
ret
;
goto
out_coeff
;
}
ret
=
regulator_disable
(
adsp
->
dvfs
);
if
(
ret
!=
0
)
{
dev_err
(
adsp
->
dev
,
"Failed to disable DCVDD: %d
\n
"
,
ret
);
return
ret
;
goto
out_coeff
;
}
}
return
0
;
out_coeff:
kfree
(
adsp
->
wm_coeff
);
return
ret
;
}
EXPORT_SYMBOL_GPL
(
wm_adsp2_init
);
sound/soc/codecs/wm_adsp.h
浏览文件 @
fbc6c4ee
...
...
@@ -30,6 +30,7 @@ struct wm_adsp_alg_region {
unsigned
int
alg
;
int
type
;
unsigned
int
base
;
size_t
len
;
};
struct
wm_adsp
{
...
...
@@ -55,6 +56,8 @@ struct wm_adsp {
bool
running
;
struct
regulator
*
dvfs
;
struct
wm_coeff
*
wm_coeff
;
};
#define WM_ADSP1(wname, num) \
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录