Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
e768f4e1
Commit
e768f4e1
authored
Jun 17, 2013
by
Mark Brown
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'asoc/topic/adsp' into asoc-next
parents
0ee6f750
0c2e3f34
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
455 additions
and
7 deletions
+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
No files found.
sound/soc/codecs/wm_adsp.c
View file @
e768f4e1
...
...
@@ -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
View file @
e768f4e1
...
...
@@ -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) \
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment