Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
L
linux-davinci
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
linux
linux-davinci
Commits
e370f45a
Commit
e370f45a
authored
Jun 22, 2009
by
Mark Brown
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'wm8961' into for-2.6.32
parents
f274143f
74dc55ed
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
2181 additions
and
0 deletions
+2181
-0
sound/soc/codecs/Kconfig
sound/soc/codecs/Kconfig
+4
-0
sound/soc/codecs/Makefile
sound/soc/codecs/Makefile
+2
-0
sound/soc/codecs/wm8961.c
sound/soc/codecs/wm8961.c
+1309
-0
sound/soc/codecs/wm8961.h
sound/soc/codecs/wm8961.h
+866
-0
No files found.
sound/soc/codecs/Kconfig
View file @
e370f45a
...
...
@@ -39,6 +39,7 @@ config SND_SOC_ALL_CODECS
select SND_SOC_WM8903 if I2C
select SND_SOC_WM8940 if I2C
select SND_SOC_WM8960 if I2C
select SND_SOC_WM8961 if I2C
select SND_SOC_WM8971 if I2C
select SND_SOC_WM8988 if SND_SOC_I2C_AND_SPI
select SND_SOC_WM8990 if I2C
...
...
@@ -156,6 +157,9 @@ config SND_SOC_WM8940
config SND_SOC_WM8960
tristate
config SND_SOC_WM8961
tristate
config SND_SOC_WM8971
tristate
...
...
sound/soc/codecs/Makefile
View file @
e370f45a
...
...
@@ -27,6 +27,7 @@ snd-soc-wm8900-objs := wm8900.o
snd-soc-wm8903-objs
:=
wm8903.o
snd-soc-wm8940-objs
:=
wm8940.o
snd-soc-wm8960-objs
:=
wm8960.o
snd-soc-wm8961-objs
:=
wm8961.o
snd-soc-wm8971-objs
:=
wm8971.o
snd-soc-wm8988-objs
:=
wm8988.o
snd-soc-wm8990-objs
:=
wm8990.o
...
...
@@ -65,6 +66,7 @@ obj-$(CONFIG_SND_SOC_WM8903) += snd-soc-wm8903.o
obj-$(CONFIG_SND_SOC_WM8971)
+=
snd-soc-wm8971.o
obj-$(CONFIG_SND_SOC_WM8940)
+=
snd-soc-wm8940.o
obj-$(CONFIG_SND_SOC_WM8960)
+=
snd-soc-wm8960.o
obj-$(CONFIG_SND_SOC_WM8961)
+=
snd-soc-wm8961.o
obj-$(CONFIG_SND_SOC_WM8988)
+=
snd-soc-wm8988.o
obj-$(CONFIG_SND_SOC_WM8990)
+=
snd-soc-wm8990.o
obj-$(CONFIG_SND_SOC_WM9081)
+=
snd-soc-wm9081.o
...
...
sound/soc/codecs/wm8961.c
0 → 100644
View file @
e370f45a
/*
* wm8961.c -- WM8961 ALSA SoC Audio driver
*
* Author: Mark Brown
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Currently unimplemented features:
* - ALC
*/
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/i2c.h>
#include <linux/platform_device.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/soc-dapm.h>
#include <sound/initval.h>
#include <sound/tlv.h>
#include "wm8961.h"
#define WM8961_MAX_REGISTER 0xFC
static
u16
wm8961_reg_defaults
[]
=
{
0x009F
,
/* R0 - Left Input volume */
0x009F
,
/* R1 - Right Input volume */
0x0000
,
/* R2 - LOUT1 volume */
0x0000
,
/* R3 - ROUT1 volume */
0x0020
,
/* R4 - Clocking1 */
0x0008
,
/* R5 - ADC & DAC Control 1 */
0x0000
,
/* R6 - ADC & DAC Control 2 */
0x000A
,
/* R7 - Audio Interface 0 */
0x01F4
,
/* R8 - Clocking2 */
0x0000
,
/* R9 - Audio Interface 1 */
0x00FF
,
/* R10 - Left DAC volume */
0x00FF
,
/* R11 - Right DAC volume */
0x0000
,
/* R12 */
0x0000
,
/* R13 */
0x0040
,
/* R14 - Audio Interface 2 */
0x0000
,
/* R15 - Software Reset */
0x0000
,
/* R16 */
0x007B
,
/* R17 - ALC1 */
0x0000
,
/* R18 - ALC2 */
0x0032
,
/* R19 - ALC3 */
0x0000
,
/* R20 - Noise Gate */
0x00C0
,
/* R21 - Left ADC volume */
0x00C0
,
/* R22 - Right ADC volume */
0x0120
,
/* R23 - Additional control(1) */
0x0000
,
/* R24 - Additional control(2) */
0x0000
,
/* R25 - Pwr Mgmt (1) */
0x0000
,
/* R26 - Pwr Mgmt (2) */
0x0000
,
/* R27 - Additional Control (3) */
0x0000
,
/* R28 - Anti-pop */
0x0000
,
/* R29 */
0x005F
,
/* R30 - Clocking 3 */
0x0000
,
/* R31 */
0x0000
,
/* R32 - ADCL signal path */
0x0000
,
/* R33 - ADCR signal path */
0x0000
,
/* R34 */
0x0000
,
/* R35 */
0x0000
,
/* R36 */
0x0000
,
/* R37 */
0x0000
,
/* R38 */
0x0000
,
/* R39 */
0x0000
,
/* R40 - LOUT2 volume */
0x0000
,
/* R41 - ROUT2 volume */
0x0000
,
/* R42 */
0x0000
,
/* R43 */
0x0000
,
/* R44 */
0x0000
,
/* R45 */
0x0000
,
/* R46 */
0x0000
,
/* R47 - Pwr Mgmt (3) */
0x0023
,
/* R48 - Additional Control (4) */
0x0000
,
/* R49 - Class D Control 1 */
0x0000
,
/* R50 */
0x0003
,
/* R51 - Class D Control 2 */
0x0000
,
/* R52 */
0x0000
,
/* R53 */
0x0000
,
/* R54 */
0x0000
,
/* R55 */
0x0106
,
/* R56 - Clocking 4 */
0x0000
,
/* R57 - DSP Sidetone 0 */
0x0000
,
/* R58 - DSP Sidetone 1 */
0x0000
,
/* R59 */
0x0000
,
/* R60 - DC Servo 0 */
0x0000
,
/* R61 - DC Servo 1 */
0x0000
,
/* R62 */
0x015E
,
/* R63 - DC Servo 3 */
0x0010
,
/* R64 */
0x0010
,
/* R65 - DC Servo 5 */
0x0000
,
/* R66 */
0x0001
,
/* R67 */
0x0003
,
/* R68 - Analogue PGA Bias */
0x0000
,
/* R69 - Analogue HP 0 */
0x0060
,
/* R70 */
0x01FB
,
/* R71 - Analogue HP 2 */
0x0000
,
/* R72 - Charge Pump 1 */
0x0065
,
/* R73 */
0x005F
,
/* R74 */
0x0059
,
/* R75 */
0x006B
,
/* R76 */
0x0038
,
/* R77 */
0x000C
,
/* R78 */
0x000A
,
/* R79 */
0x006B
,
/* R80 */
0x0000
,
/* R81 */
0x0000
,
/* R82 - Charge Pump B */
0x0087
,
/* R83 */
0x0000
,
/* R84 */
0x005C
,
/* R85 */
0x0000
,
/* R86 */
0x0000
,
/* R87 - Write Sequencer 1 */
0x0000
,
/* R88 - Write Sequencer 2 */
0x0000
,
/* R89 - Write Sequencer 3 */
0x0000
,
/* R90 - Write Sequencer 4 */
0x0000
,
/* R91 - Write Sequencer 5 */
0x0000
,
/* R92 - Write Sequencer 6 */
0x0000
,
/* R93 - Write Sequencer 7 */
0x0000
,
/* R94 */
0x0000
,
/* R95 */
0x0000
,
/* R96 */
0x0000
,
/* R97 */
0x0000
,
/* R98 */
0x0000
,
/* R99 */
0x0000
,
/* R100 */
0x0000
,
/* R101 */
0x0000
,
/* R102 */
0x0000
,
/* R103 */
0x0000
,
/* R104 */
0x0000
,
/* R105 */
0x0000
,
/* R106 */
0x0000
,
/* R107 */
0x0000
,
/* R108 */
0x0000
,
/* R109 */
0x0000
,
/* R110 */
0x0000
,
/* R111 */
0x0000
,
/* R112 */
0x0000
,
/* R113 */
0x0000
,
/* R114 */
0x0000
,
/* R115 */
0x0000
,
/* R116 */
0x0000
,
/* R117 */
0x0000
,
/* R118 */
0x0000
,
/* R119 */
0x0000
,
/* R120 */
0x0000
,
/* R121 */
0x0000
,
/* R122 */
0x0000
,
/* R123 */
0x0000
,
/* R124 */
0x0000
,
/* R125 */
0x0000
,
/* R126 */
0x0000
,
/* R127 */
0x0000
,
/* R128 */
0x0000
,
/* R129 */
0x0000
,
/* R130 */
0x0000
,
/* R131 */
0x0000
,
/* R132 */
0x0000
,
/* R133 */
0x0000
,
/* R134 */
0x0000
,
/* R135 */
0x0000
,
/* R136 */
0x0000
,
/* R137 */
0x0000
,
/* R138 */
0x0000
,
/* R139 */
0x0000
,
/* R140 */
0x0000
,
/* R141 */
0x0000
,
/* R142 */
0x0000
,
/* R143 */
0x0000
,
/* R144 */
0x0000
,
/* R145 */
0x0000
,
/* R146 */
0x0000
,
/* R147 */
0x0000
,
/* R148 */
0x0000
,
/* R149 */
0x0000
,
/* R150 */
0x0000
,
/* R151 */
0x0000
,
/* R152 */
0x0000
,
/* R153 */
0x0000
,
/* R154 */
0x0000
,
/* R155 */
0x0000
,
/* R156 */
0x0000
,
/* R157 */
0x0000
,
/* R158 */
0x0000
,
/* R159 */
0x0000
,
/* R160 */
0x0000
,
/* R161 */
0x0000
,
/* R162 */
0x0000
,
/* R163 */
0x0000
,
/* R164 */
0x0000
,
/* R165 */
0x0000
,
/* R166 */
0x0000
,
/* R167 */
0x0000
,
/* R168 */
0x0000
,
/* R169 */
0x0000
,
/* R170 */
0x0000
,
/* R171 */
0x0000
,
/* R172 */
0x0000
,
/* R173 */
0x0000
,
/* R174 */
0x0000
,
/* R175 */
0x0000
,
/* R176 */
0x0000
,
/* R177 */
0x0000
,
/* R178 */
0x0000
,
/* R179 */
0x0000
,
/* R180 */
0x0000
,
/* R181 */
0x0000
,
/* R182 */
0x0000
,
/* R183 */
0x0000
,
/* R184 */
0x0000
,
/* R185 */
0x0000
,
/* R186 */
0x0000
,
/* R187 */
0x0000
,
/* R188 */
0x0000
,
/* R189 */
0x0000
,
/* R190 */
0x0000
,
/* R191 */
0x0000
,
/* R192 */
0x0000
,
/* R193 */
0x0000
,
/* R194 */
0x0000
,
/* R195 */
0x0030
,
/* R196 */
0x0006
,
/* R197 */
0x0000
,
/* R198 */
0x0060
,
/* R199 */
0x0000
,
/* R200 */
0x003F
,
/* R201 */
0x0000
,
/* R202 */
0x0000
,
/* R203 */
0x0000
,
/* R204 */
0x0001
,
/* R205 */
0x0000
,
/* R206 */
0x0181
,
/* R207 */
0x0005
,
/* R208 */
0x0008
,
/* R209 */
0x0008
,
/* R210 */
0x0000
,
/* R211 */
0x013B
,
/* R212 */
0x0000
,
/* R213 */
0x0000
,
/* R214 */
0x0000
,
/* R215 */
0x0000
,
/* R216 */
0x0070
,
/* R217 */
0x0000
,
/* R218 */
0x0000
,
/* R219 */
0x0000
,
/* R220 */
0x0000
,
/* R221 */
0x0000
,
/* R222 */
0x0003
,
/* R223 */
0x0000
,
/* R224 */
0x0000
,
/* R225 */
0x0001
,
/* R226 */
0x0008
,
/* R227 */
0x0000
,
/* R228 */
0x0000
,
/* R229 */
0x0000
,
/* R230 */
0x0000
,
/* R231 */
0x0004
,
/* R232 */
0x0000
,
/* R233 */
0x0000
,
/* R234 */
0x0000
,
/* R235 */
0x0000
,
/* R236 */
0x0000
,
/* R237 */
0x0080
,
/* R238 */
0x0000
,
/* R239 */
0x0000
,
/* R240 */
0x0000
,
/* R241 */
0x0000
,
/* R242 */
0x0000
,
/* R243 */
0x0000
,
/* R244 */
0x0052
,
/* R245 */
0x0110
,
/* R246 */
0x0040
,
/* R247 */
0x0000
,
/* R248 */
0x0030
,
/* R249 */
0x0000
,
/* R250 */
0x0000
,
/* R251 */
0x0001
,
/* R252 - General test 1 */
};
struct
wm8961_priv
{
struct
snd_soc_codec
codec
;
int
sysclk
;
u16
reg_cache
[
WM8961_MAX_REGISTER
];
};
static
int
wm8961_reg_is_volatile
(
int
reg
)
{
switch
(
reg
)
{
case
WM8961_WRITE_SEQUENCER_7
:
case
WM8961_DC_SERVO_1
:
return
1
;
default:
return
0
;
}
}
static
unsigned
int
wm8961_read_reg_cache
(
struct
snd_soc_codec
*
codec
,
unsigned
int
reg
)
{
u16
*
cache
=
codec
->
reg_cache
;
BUG_ON
(
reg
>
WM8961_MAX_REGISTER
);
return
cache
[
reg
];
}
static
unsigned
int
wm8961_read_hw
(
struct
snd_soc_codec
*
codec
,
u8
reg
)
{
struct
i2c_msg
xfer
[
2
];
u16
data
;
int
ret
;
struct
i2c_client
*
client
=
codec
->
control_data
;
BUG_ON
(
reg
>
WM8961_MAX_REGISTER
);
/* Write register */
xfer
[
0
].
addr
=
client
->
addr
;
xfer
[
0
].
flags
=
0
;
xfer
[
0
].
len
=
1
;
xfer
[
0
].
buf
=
&
reg
;
/* Read data */
xfer
[
1
].
addr
=
client
->
addr
;
xfer
[
1
].
flags
=
I2C_M_RD
;
xfer
[
1
].
len
=
2
;
xfer
[
1
].
buf
=
(
u8
*
)
&
data
;
ret
=
i2c_transfer
(
client
->
adapter
,
xfer
,
2
);
if
(
ret
!=
2
)
{
dev_err
(
&
client
->
dev
,
"i2c_transfer() returned %d
\n
"
,
ret
);
return
0
;
}
return
(
data
>>
8
)
|
((
data
&
0xff
)
<<
8
);
}
static
unsigned
int
wm8961_read
(
struct
snd_soc_codec
*
codec
,
unsigned
int
reg
)
{
if
(
wm8961_reg_is_volatile
(
reg
))
return
wm8961_read_hw
(
codec
,
reg
);
else
return
wm8961_read_reg_cache
(
codec
,
reg
);
}
static
int
wm8961_write
(
struct
snd_soc_codec
*
codec
,
unsigned
int
reg
,
unsigned
int
value
)
{
u16
*
cache
=
codec
->
reg_cache
;
u8
data
[
3
];
BUG_ON
(
reg
>
WM8961_MAX_REGISTER
);
if
(
!
wm8961_reg_is_volatile
(
reg
))
cache
[
reg
]
=
value
;
data
[
0
]
=
reg
;
data
[
1
]
=
value
>>
8
;
data
[
2
]
=
value
&
0x00ff
;
if
(
codec
->
hw_write
(
codec
->
control_data
,
data
,
3
)
==
3
)
return
0
;
else
return
-
EIO
;
}
static
int
wm8961_reset
(
struct
snd_soc_codec
*
codec
)
{
return
wm8961_write
(
codec
,
WM8961_SOFTWARE_RESET
,
0
);
}
/*
* The headphone output supports special anti-pop sequences giving
* silent power up and power down.
*/
static
int
wm8961_hp_event
(
struct
snd_soc_dapm_widget
*
w
,
struct
snd_kcontrol
*
kcontrol
,
int
event
)
{
struct
snd_soc_codec
*
codec
=
w
->
codec
;
u16
hp_reg
=
wm8961_read
(
codec
,
WM8961_ANALOGUE_HP_0
);
u16
cp_reg
=
wm8961_read
(
codec
,
WM8961_CHARGE_PUMP_1
);
u16
pwr_reg
=
wm8961_read
(
codec
,
WM8961_PWR_MGMT_2
);
u16
dcs_reg
=
wm8961_read
(
codec
,
WM8961_DC_SERVO_1
);
int
timeout
=
500
;
if
(
event
&
SND_SOC_DAPM_POST_PMU
)
{
/* Make sure the output is shorted */
hp_reg
&=
~
(
WM8961_HPR_RMV_SHORT
|
WM8961_HPL_RMV_SHORT
);
wm8961_write
(
codec
,
WM8961_ANALOGUE_HP_0
,
hp_reg
);
/* Enable the charge pump */
cp_reg
|=
WM8961_CP_ENA
;
wm8961_write
(
codec
,
WM8961_CHARGE_PUMP_1
,
cp_reg
);
mdelay
(
5
);
/* Enable the PGA */
pwr_reg
|=
WM8961_LOUT1_PGA
|
WM8961_ROUT1_PGA
;
wm8961_write
(
codec
,
WM8961_PWR_MGMT_2
,
pwr_reg
);
/* Enable the amplifier */
hp_reg
|=
WM8961_HPR_ENA
|
WM8961_HPL_ENA
;
wm8961_write
(
codec
,
WM8961_ANALOGUE_HP_0
,
hp_reg
);
/* Second stage enable */
hp_reg
|=
WM8961_HPR_ENA_DLY
|
WM8961_HPL_ENA_DLY
;
wm8961_write
(
codec
,
WM8961_ANALOGUE_HP_0
,
hp_reg
);
/* Enable the DC servo & trigger startup */
dcs_reg
|=
WM8961_DCS_ENA_CHAN_HPR
|
WM8961_DCS_TRIG_STARTUP_HPR
|
WM8961_DCS_ENA_CHAN_HPL
|
WM8961_DCS_TRIG_STARTUP_HPL
;
dev_dbg
(
codec
->
dev
,
"Enabling DC servo
\n
"
);
wm8961_write
(
codec
,
WM8961_DC_SERVO_1
,
dcs_reg
);
do
{
msleep
(
1
);
dcs_reg
=
wm8961_read
(
codec
,
WM8961_DC_SERVO_1
);
}
while
(
--
timeout
&&
dcs_reg
&
(
WM8961_DCS_TRIG_STARTUP_HPR
|
WM8961_DCS_TRIG_STARTUP_HPL
));
if
(
dcs_reg
&
(
WM8961_DCS_TRIG_STARTUP_HPR
|
WM8961_DCS_TRIG_STARTUP_HPL
))
dev_err
(
codec
->
dev
,
"DC servo timed out
\n
"
);
else
dev_dbg
(
codec
->
dev
,
"DC servo startup complete
\n
"
);
/* Enable the output stage */
hp_reg
|=
WM8961_HPR_ENA_OUTP
|
WM8961_HPL_ENA_OUTP
;
wm8961_write
(
codec
,
WM8961_ANALOGUE_HP_0
,
hp_reg
);
/* Remove the short on the output stage */
hp_reg
|=
WM8961_HPR_RMV_SHORT
|
WM8961_HPL_RMV_SHORT
;
wm8961_write
(
codec
,
WM8961_ANALOGUE_HP_0
,
hp_reg
);
}
if
(
event
&
SND_SOC_DAPM_PRE_PMD
)
{
/* Short the output */
hp_reg
&=
~
(
WM8961_HPR_RMV_SHORT
|
WM8961_HPL_RMV_SHORT
);
wm8961_write
(
codec
,
WM8961_ANALOGUE_HP_0
,
hp_reg
);
/* Disable the output stage */
hp_reg
&=
~
(
WM8961_HPR_ENA_OUTP
|
WM8961_HPL_ENA_OUTP
);
wm8961_write
(
codec
,
WM8961_ANALOGUE_HP_0
,
hp_reg
);
/* Disable DC offset cancellation */
dcs_reg
&=
~
(
WM8961_DCS_ENA_CHAN_HPR
|
WM8961_DCS_ENA_CHAN_HPL
);
wm8961_write
(
codec
,
WM8961_DC_SERVO_1
,
dcs_reg
);
/* Finish up */
hp_reg
&=
~
(
WM8961_HPR_ENA_DLY
|
WM8961_HPR_ENA
|
WM8961_HPL_ENA_DLY
|
WM8961_HPL_ENA
);
wm8961_write
(
codec
,
WM8961_ANALOGUE_HP_0
,
hp_reg
);
/* Disable the PGA */
pwr_reg
&=
~
(
WM8961_LOUT1_PGA
|
WM8961_ROUT1_PGA
);
wm8961_write
(
codec
,
WM8961_PWR_MGMT_2
,
pwr_reg
);
/* Disable the charge pump */
dev_dbg
(
codec
->
dev
,
"Disabling charge pump
\n
"
);
wm8961_write
(
codec
,
WM8961_CHARGE_PUMP_1
,
cp_reg
&
~
WM8961_CP_ENA
);
}
return
0
;
}
static
int
wm8961_spk_event
(
struct
snd_soc_dapm_widget
*
w
,
struct
snd_kcontrol
*
kcontrol
,
int
event
)
{
struct
snd_soc_codec
*
codec
=
w
->
codec
;
u16
pwr_reg
=
wm8961_read
(
codec
,
WM8961_PWR_MGMT_2
);
u16
spk_reg
=
wm8961_read
(
codec
,
WM8961_CLASS_D_CONTROL_1
);
if
(
event
&
SND_SOC_DAPM_POST_PMU
)
{
/* Enable the PGA */
pwr_reg
|=
WM8961_SPKL_PGA
|
WM8961_SPKR_PGA
;
wm8961_write
(
codec
,
WM8961_PWR_MGMT_2
,
pwr_reg
);
/* Enable the amplifier */
spk_reg
|=
WM8961_SPKL_ENA
|
WM8961_SPKR_ENA
;
wm8961_write
(
codec
,
WM8961_CLASS_D_CONTROL_1
,
spk_reg
);
}
if
(
event
&
SND_SOC_DAPM_PRE_PMD
)
{
/* Enable the amplifier */
spk_reg
&=
~
(
WM8961_SPKL_ENA
|
WM8961_SPKR_ENA
);
wm8961_write
(
codec
,
WM8961_CLASS_D_CONTROL_1
,
spk_reg
);
/* Enable the PGA */
pwr_reg
&=
~
(
WM8961_SPKL_PGA
|
WM8961_SPKR_PGA
);
wm8961_write
(
codec
,
WM8961_PWR_MGMT_2
,
pwr_reg
);
}
return
0
;
}
static
const
char
*
adc_hpf_text
[]
=
{
"Hi-fi"
,
"Voice 1"
,
"Voice 2"
,
"Voice 3"
,
};
static
const
struct
soc_enum
adc_hpf
=
SOC_ENUM_SINGLE
(
WM8961_ADC_DAC_CONTROL_2
,
7
,
4
,
adc_hpf_text
);
static
const
char
*
dac_deemph_text
[]
=
{
"None"
,
"32kHz"
,
"44.1kHz"
,
"48kHz"
,
};
static
const
struct
soc_enum
dac_deemph
=
SOC_ENUM_SINGLE
(
WM8961_ADC_DAC_CONTROL_1
,
1
,
4
,
dac_deemph_text
);
static
const
DECLARE_TLV_DB_SCALE
(
out_tlv
,
-
12100
,
100
,
1
);
static
const
DECLARE_TLV_DB_SCALE
(
hp_sec_tlv
,
-
700
,
100
,
0
);
static
const
DECLARE_TLV_DB_SCALE
(
adc_tlv
,
-
7200
,
75
,
1
);
static
const
DECLARE_TLV_DB_SCALE
(
sidetone_tlv
,
-
3600
,
300
,
0
);
static
unsigned
int
boost_tlv
[]
=
{
TLV_DB_RANGE_HEAD
(
4
),
0
,
0
,
TLV_DB_SCALE_ITEM
(
0
,
0
,
0
),
1
,
1
,
TLV_DB_SCALE_ITEM
(
13
,
0
,
0
),
2
,
2
,
TLV_DB_SCALE_ITEM
(
20
,
0
,
0
),
3
,
3
,
TLV_DB_SCALE_ITEM
(
29
,
0
,
0
),
};
static
const
DECLARE_TLV_DB_SCALE
(
pga_tlv
,
-
2325
,
75
,
0
);
static
const
struct
snd_kcontrol_new
wm8961_snd_controls
[]
=
{
SOC_DOUBLE_R_TLV
(
"Headphone Volume"
,
WM8961_LOUT1_VOLUME
,
WM8961_ROUT1_VOLUME
,
0
,
127
,
0
,
out_tlv
),
SOC_DOUBLE_TLV
(
"Headphone Secondary Volume"
,
WM8961_ANALOGUE_HP_2
,
6
,
3
,
7
,
0
,
hp_sec_tlv
),
SOC_DOUBLE_R
(
"Headphone ZC Switch"
,
WM8961_LOUT1_VOLUME
,
WM8961_ROUT1_VOLUME
,
7
,
1
,
0
),
SOC_DOUBLE_R_TLV
(
"Speaker Volume"
,
WM8961_LOUT2_VOLUME
,
WM8961_ROUT2_VOLUME
,
0
,
127
,
0
,
out_tlv
),
SOC_DOUBLE_R
(
"Speaker ZC Switch"
,
WM8961_LOUT2_VOLUME
,
WM8961_ROUT2_VOLUME
,
7
,
1
,
0
),
SOC_SINGLE
(
"Speaker AC Gain"
,
WM8961_CLASS_D_CONTROL_2
,
0
,
7
,
0
),
SOC_SINGLE
(
"DAC x128 OSR Switch"
,
WM8961_ADC_DAC_CONTROL_2
,
0
,
1
,
0
),
SOC_ENUM
(
"DAC Deemphasis"
,
dac_deemph
),
SOC_SINGLE
(
"DAC Soft Mute Switch"
,
WM8961_ADC_DAC_CONTROL_2
,
3
,
1
,
0
),
SOC_DOUBLE_R_TLV
(
"Sidetone Volume"
,
WM8961_DSP_SIDETONE_0
,
WM8961_DSP_SIDETONE_1
,
4
,
12
,
0
,
sidetone_tlv
),
SOC_SINGLE
(
"ADC High Pass Filter Switch"
,
WM8961_ADC_DAC_CONTROL_1
,
0
,
1
,
0
),
SOC_ENUM
(
"ADC High Pass Filter Mode"
,
adc_hpf
),
SOC_DOUBLE_R_TLV
(
"Capture Volume"
,
WM8961_LEFT_ADC_VOLUME
,
WM8961_RIGHT_ADC_VOLUME
,
1
,
119
,
0
,
adc_tlv
),
SOC_DOUBLE_R_TLV
(
"Capture Boost Volume"
,
WM8961_ADCL_SIGNAL_PATH
,
WM8961_ADCR_SIGNAL_PATH
,
4
,
3
,
0
,
boost_tlv
),
SOC_DOUBLE_R_TLV
(
"Capture PGA Volume"
,
WM8961_LEFT_INPUT_VOLUME
,
WM8961_RIGHT_INPUT_VOLUME
,
0
,
62
,
0
,
pga_tlv
),
SOC_DOUBLE_R
(
"Capture PGA ZC Switch"
,
WM8961_LEFT_INPUT_VOLUME
,
WM8961_RIGHT_INPUT_VOLUME
,
6
,
1
,
1
),
SOC_DOUBLE_R
(
"Capture PGA Switch"
,
WM8961_LEFT_INPUT_VOLUME
,
WM8961_RIGHT_INPUT_VOLUME
,
7
,
1
,
1
),
};
static
const
char
*
sidetone_text
[]
=
{
"None"
,
"Left"
,
"Right"
};
static
const
struct
soc_enum
dacl_sidetone
=
SOC_ENUM_SINGLE
(
WM8961_DSP_SIDETONE_0
,
2
,
3
,
sidetone_text
);
static
const
struct
soc_enum
dacr_sidetone
=
SOC_ENUM_SINGLE
(
WM8961_DSP_SIDETONE_1
,
2
,
3
,
sidetone_text
);
static
const
struct
snd_kcontrol_new
dacl_mux
=
SOC_DAPM_ENUM
(
"DACL Sidetone"
,
dacl_sidetone
);
static
const
struct
snd_kcontrol_new
dacr_mux
=
SOC_DAPM_ENUM
(
"DACR Sidetone"
,
dacr_sidetone
);
static
const
struct
snd_soc_dapm_widget
wm8961_dapm_widgets
[]
=
{
SND_SOC_DAPM_INPUT
(
"LINPUT"
),
SND_SOC_DAPM_INPUT
(
"RINPUT"
),
SND_SOC_DAPM_SUPPLY
(
"CLK_DSP"
,
WM8961_CLOCKING2
,
4
,
0
,
NULL
,
0
),
SND_SOC_DAPM_PGA
(
"Left Input"
,
WM8961_PWR_MGMT_1
,
5
,
0
,
NULL
,
0
),
SND_SOC_DAPM_PGA
(
"Right Input"
,
WM8961_PWR_MGMT_1
,
4
,
0
,
NULL
,
0
),
SND_SOC_DAPM_ADC
(
"ADCL"
,
"HiFi Capture"
,
WM8961_PWR_MGMT_1
,
3
,
0
),
SND_SOC_DAPM_ADC
(
"ADCR"
,
"HiFi Capture"
,
WM8961_PWR_MGMT_1
,
2
,
0
),
SND_SOC_DAPM_MICBIAS
(
"MICBIAS"
,
WM8961_PWR_MGMT_1
,
1
,
0
),
SND_SOC_DAPM_MUX
(
"DACL Sidetone"
,
SND_SOC_NOPM
,
0
,
0
,
&
dacl_mux
),
SND_SOC_DAPM_MUX
(
"DACR Sidetone"
,
SND_SOC_NOPM
,
0
,
0
,
&
dacr_mux
),
SND_SOC_DAPM_DAC
(
"DACL"
,
"HiFi Playback"
,
WM8961_PWR_MGMT_2
,
8
,
0
),
SND_SOC_DAPM_DAC
(
"DACR"
,
"HiFi Playback"
,
WM8961_PWR_MGMT_2
,
7
,
0
),
/* Handle as a mono path for DCS */
SND_SOC_DAPM_PGA_E
(
"Headphone Output"
,
SND_SOC_NOPM
,
4
,
0
,
NULL
,
0
,
wm8961_hp_event
,
SND_SOC_DAPM_POST_PMU
|
SND_SOC_DAPM_PRE_PMD
),
SND_SOC_DAPM_PGA_E
(
"Speaker Output"
,
SND_SOC_NOPM
,
4
,
0
,
NULL
,
0
,
wm8961_spk_event
,
SND_SOC_DAPM_POST_PMU
|
SND_SOC_DAPM_PRE_PMD
),
SND_SOC_DAPM_OUTPUT
(
"HP_L"
),
SND_SOC_DAPM_OUTPUT
(
"HP_R"
),
SND_SOC_DAPM_OUTPUT
(
"SPK_LN"
),
SND_SOC_DAPM_OUTPUT
(
"SPK_LP"
),
SND_SOC_DAPM_OUTPUT
(
"SPK_RN"
),
SND_SOC_DAPM_OUTPUT
(
"SPK_RP"
),
};
static
const
struct
snd_soc_dapm_route
audio_paths
[]
=
{
{
"DACL"
,
NULL
,
"CLK_DSP"
},
{
"DACL"
,
NULL
,
"DACL Sidetone"
},
{
"DACR"
,
NULL
,
"CLK_DSP"
},
{
"DACR"
,
NULL
,
"DACR Sidetone"
},
{
"DACL Sidetone"
,
"Left"
,
"ADCL"
},
{
"DACL Sidetone"
,
"Right"
,
"ADCR"
},
{
"DACR Sidetone"
,
"Left"
,
"ADCL"
},
{
"DACR Sidetone"
,
"Right"
,
"ADCR"
},
{
"HP_L"
,
NULL
,
"Headphone Output"
},
{
"HP_R"
,
NULL
,
"Headphone Output"
},
{
"Headphone Output"
,
NULL
,
"DACL"
},
{
"Headphone Output"
,
NULL
,
"DACR"
},
{
"SPK_LN"
,
NULL
,
"Speaker Output"
},
{
"SPK_LP"
,
NULL
,
"Speaker Output"
},
{
"SPK_RN"
,
NULL
,
"Speaker Output"
},
{
"SPK_RP"
,
NULL
,
"Speaker Output"
},
{
"Speaker Output"
,
NULL
,
"DACL"
},
{
"Speaker Output"
,
NULL
,
"DACR"
},
{
"ADCL"
,
NULL
,
"Left Input"
},
{
"ADCL"
,
NULL
,
"CLK_DSP"
},
{
"ADCR"
,
NULL
,
"Right Input"
},
{
"ADCR"
,
NULL
,
"CLK_DSP"
},
{
"Left Input"
,
NULL
,
"LINPUT"
},
{
"Right Input"
,
NULL
,
"RINPUT"
},
};
/* Values for CLK_SYS_RATE */
static
struct
{
int
ratio
;
u16
val
;
}
wm8961_clk_sys_ratio
[]
=
{
{
64
,
0
},
{
128
,
1
},
{
192
,
2
},
{
256
,
3
},
{
384
,
4
},
{
512
,
5
},
{
768
,
6
},
{
1024
,
7
},
{
1408
,
8
},
{
1536
,
9
},
};
/* Values for SAMPLE_RATE */
static
struct
{
int
rate
;
u16
val
;
}
wm8961_srate
[]
=
{
{
48000
,
0
},
{
44100
,
0
},
{
32000
,
1
},
{
22050
,
2
},
{
24000
,
2
},
{
16000
,
3
},
{
11250
,
4
},
{
12000
,
4
},
{
8000
,
5
},
};
static
int
wm8961_hw_params
(
struct
snd_pcm_substream
*
substream
,
struct
snd_pcm_hw_params
*
params
,
struct
snd_soc_dai
*
dai
)
{
struct
snd_soc_codec
*
codec
=
dai
->
codec
;
struct
wm8961_priv
*
wm8961
=
codec
->
private_data
;
int
i
,
best
,
target
,
fs
;
u16
reg
;
fs
=
params_rate
(
params
);
if
(
!
wm8961
->
sysclk
)
{
dev_err
(
codec
->
dev
,
"MCLK has not been specified
\n
"
);
return
-
EINVAL
;
}
/* Find the closest sample rate for the filters */
best
=
0
;
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
wm8961_srate
);
i
++
)
{
if
(
abs
(
wm8961_srate
[
i
].
rate
-
fs
)
<
abs
(
wm8961_srate
[
best
].
rate
-
fs
))
best
=
i
;
}
reg
=
wm8961_read
(
codec
,
WM8961_ADDITIONAL_CONTROL_3
);
reg
&=
~
WM8961_SAMPLE_RATE_MASK
;
reg
|=
wm8961_srate
[
best
].
val
;
wm8961_write
(
codec
,
WM8961_ADDITIONAL_CONTROL_3
,
reg
);
dev_dbg
(
codec
->
dev
,
"Selected SRATE %dHz for %dHz
\n
"
,
wm8961_srate
[
best
].
rate
,
fs
);
/* Select a CLK_SYS/fs ratio equal to or higher than required */
target
=
wm8961
->
sysclk
/
fs
;
if
(
substream
->
stream
==
SNDRV_PCM_STREAM_PLAYBACK
&&
target
<
64
)
{
dev_err
(
codec
->
dev
,
"SYSCLK must be at least 64*fs for DAC
\n
"
);
return
-
EINVAL
;
}
if
(
substream
->
stream
==
SNDRV_PCM_STREAM_CAPTURE
&&
target
<
256
)
{
dev_err
(
codec
->
dev
,
"SYSCLK must be at least 256*fs for ADC
\n
"
);
return
-
EINVAL
;
}
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
wm8961_clk_sys_ratio
);
i
++
)
{
if
(
wm8961_clk_sys_ratio
[
i
].
ratio
>=
target
)
break
;
}
if
(
i
==
ARRAY_SIZE
(
wm8961_clk_sys_ratio
))
{
dev_err
(
codec
->
dev
,
"Unable to generate CLK_SYS_RATE
\n
"
);
return
-
EINVAL
;
}
dev_dbg
(
codec
->
dev
,
"Selected CLK_SYS_RATE of %d for %d/%d=%d
\n
"
,
wm8961_clk_sys_ratio
[
i
].
ratio
,
wm8961
->
sysclk
,
fs
,
wm8961
->
sysclk
/
fs
);
reg
=
wm8961_read
(
codec
,
WM8961_CLOCKING_4
);
reg
&=
~
WM8961_CLK_SYS_RATE_MASK
;
reg
|=
wm8961_clk_sys_ratio
[
i
].
val
<<
WM8961_CLK_SYS_RATE_SHIFT
;
wm8961_write
(
codec
,
WM8961_CLOCKING_4
,
reg
);
reg
=
wm8961_read
(
codec
,
WM8961_AUDIO_INTERFACE_0
);
reg
&=
~
WM8961_WL_MASK
;
switch
(
params_format
(
params
))
{
case
SNDRV_PCM_FORMAT_S16_LE
:
break
;
case
SNDRV_PCM_FORMAT_S20_3LE
:
reg
|=
1
<<
WM8961_WL_SHIFT
;
break
;
case
SNDRV_PCM_FORMAT_S24_LE
:
reg
|=
2
<<
WM8961_WL_SHIFT
;
break
;
case
SNDRV_PCM_FORMAT_S32_LE
:
reg
|=
3
<<
WM8961_WL_SHIFT
;
break
;
default:
return
-
EINVAL
;
}
wm8961_write
(
codec
,
WM8961_AUDIO_INTERFACE_0
,
reg
);
/* Sloping stop-band filter is recommended for <= 24kHz */
reg
=
wm8961_read
(
codec
,
WM8961_ADC_DAC_CONTROL_2
);
if
(
fs
<=
24000
)
reg
|=
WM8961_DACSLOPE
;
else
reg
&=
WM8961_DACSLOPE
;
wm8961_write
(
codec
,
WM8961_ADC_DAC_CONTROL_2
,
reg
);
return
0
;
}
static
int
wm8961_set_sysclk
(
struct
snd_soc_dai
*
dai
,
int
clk_id
,
unsigned
int
freq
,
int
dir
)
{
struct
snd_soc_codec
*
codec
=
dai
->
codec
;
struct
wm8961_priv
*
wm8961
=
codec
->
private_data
;
u16
reg
=
wm8961_read
(
codec
,
WM8961_CLOCKING1
);
if
(
freq
>
33000000
)
{
dev_err
(
codec
->
dev
,
"MCLK must be <33MHz
\n
"
);
return
-
EINVAL
;
}
if
(
freq
>
16500000
)
{
dev_dbg
(
codec
->
dev
,
"Using MCLK/2 for %dHz MCLK
\n
"
,
freq
);
reg
|=
WM8961_MCLKDIV
;
freq
/=
2
;
}
else
{
dev_dbg
(
codec
->
dev
,
"Using MCLK/1 for %dHz MCLK
\n
"
,
freq
);
reg
&=
WM8961_MCLKDIV
;
}
wm8961_write
(
codec
,
WM8961_CLOCKING1
,
reg
);
wm8961
->
sysclk
=
freq
;
return
0
;
}
static
int
wm8961_set_fmt
(
struct
snd_soc_dai
*
dai
,
unsigned
int
fmt
)
{
struct
snd_soc_codec
*
codec
=
dai
->
codec
;
u16
aif
=
wm8961_read
(
codec
,
WM8961_AUDIO_INTERFACE_0
);
aif
&=
~
(
WM8961_BCLKINV
|
WM8961_LRP
|
WM8961_MS
|
WM8961_FORMAT_MASK
);
switch
(
fmt
&
SND_SOC_DAIFMT_MASTER_MASK
)
{
case
SND_SOC_DAIFMT_CBM_CFM
:
aif
|=
WM8961_MS
;
break
;
case
SND_SOC_DAIFMT_CBS_CFS
:
break
;
default:
return
-
EINVAL
;
}
switch
(
fmt
&
SND_SOC_DAIFMT_FORMAT_MASK
)
{
case
SND_SOC_DAIFMT_RIGHT_J
:
break
;
case
SND_SOC_DAIFMT_LEFT_J
:
aif
|=
1
;
break
;
case
SND_SOC_DAIFMT_I2S
:
aif
|=
2
;
break
;
case
SND_SOC_DAIFMT_DSP_B
:
aif
|=
WM8961_LRP
;
case
SND_SOC_DAIFMT_DSP_A
:
aif
|=
3
;
switch
(
fmt
&
SND_SOC_DAIFMT_INV_MASK
)
{
case
SND_SOC_DAIFMT_NB_NF
:
case
SND_SOC_DAIFMT_IB_NF
:
break
;
default:
return
-
EINVAL
;
}
break
;
default:
return
-
EINVAL
;
}
switch
(
fmt
&
SND_SOC_DAIFMT_INV_MASK
)
{
case
SND_SOC_DAIFMT_NB_NF
:
break
;
case
SND_SOC_DAIFMT_NB_IF
:
aif
|=
WM8961_LRP
;
break
;
case
SND_SOC_DAIFMT_IB_NF
:
aif
|=
WM8961_BCLKINV
;
break
;
case
SND_SOC_DAIFMT_IB_IF
:
aif
|=
WM8961_BCLKINV
|
WM8961_LRP
;
break
;
default:
return
-
EINVAL
;
}
return
wm8961_write
(
codec
,
WM8961_AUDIO_INTERFACE_0
,
aif
);
}
static
int
wm8961_set_tristate
(
struct
snd_soc_dai
*
dai
,
int
tristate
)
{
struct
snd_soc_codec
*
codec
=
dai
->
codec
;
u16
reg
=
wm8961_read
(
codec
,
WM8961_ADDITIONAL_CONTROL_2
);
if
(
tristate
)
reg
|=
WM8961_TRIS
;
else
reg
&=
~
WM8961_TRIS
;
return
wm8961_write
(
codec
,
WM8961_ADDITIONAL_CONTROL_2
,
reg
);
}
static
int
wm8961_digital_mute
(
struct
snd_soc_dai
*
dai
,
int
mute
)
{
struct
snd_soc_codec
*
codec
=
dai
->
codec
;
u16
reg
=
wm8961_read
(
codec
,
WM8961_ADC_DAC_CONTROL_1
);
if
(
mute
)
reg
|=
WM8961_DACMU
;
else
reg
&=
~
WM8961_DACMU
;
msleep
(
17
);
return
wm8961_write
(
codec
,
WM8961_ADC_DAC_CONTROL_1
,
reg
);
}
static
int
wm8961_set_clkdiv
(
struct
snd_soc_dai
*
dai
,
int
div_id
,
int
div
)
{
struct
snd_soc_codec
*
codec
=
dai
->
codec
;
u16
reg
;
switch
(
div_id
)
{
case
WM8961_BCLK
:
reg
=
wm8961_read
(
codec
,
WM8961_CLOCKING2
);
reg
&=
~
WM8961_BCLKDIV_MASK
;
reg
|=
div
;
wm8961_write
(
codec
,
WM8961_CLOCKING2
,
reg
);
break
;
case
WM8961_LRCLK
:
reg
=
wm8961_read
(
codec
,
WM8961_AUDIO_INTERFACE_2
);
reg
&=
~
WM8961_LRCLK_RATE_MASK
;
reg
|=
div
;
wm8961_write
(
codec
,
WM8961_AUDIO_INTERFACE_2
,
reg
);
break
;
default:
return
-
EINVAL
;
}
return
0
;
}
static
int
wm8961_set_bias_level
(
struct
snd_soc_codec
*
codec
,
enum
snd_soc_bias_level
level
)
{
u16
reg
;
/* This is all slightly unusual since we have no bypass paths
* and the output amplifier structure means we can just slam
* the biases straight up rather than having to ramp them
* slowly.
*/
switch
(
level
)
{
case
SND_SOC_BIAS_ON
:
break
;
case
SND_SOC_BIAS_PREPARE
:
if
(
codec
->
bias_level
==
SND_SOC_BIAS_STANDBY
)
{
/* Enable bias generation */
reg
=
wm8961_read
(
codec
,
WM8961_ANTI_POP
);
reg
|=
WM8961_BUFIOEN
|
WM8961_BUFDCOPEN
;
wm8961_write
(
codec
,
WM8961_ANTI_POP
,
reg
);
/* VMID=2*50k, VREF */
reg
=
wm8961_read
(
codec
,
WM8961_PWR_MGMT_1
);
reg
&=
~
WM8961_VMIDSEL_MASK
;
reg
|=
(
1
<<
WM8961_VMIDSEL_SHIFT
)
|
WM8961_VREF
;
wm8961_write
(
codec
,
WM8961_PWR_MGMT_1
,
reg
);
}
break
;
case
SND_SOC_BIAS_STANDBY
:
if
(
codec
->
bias_level
==
SND_SOC_BIAS_PREPARE
)
{
/* VREF off */
reg
=
wm8961_read
(
codec
,
WM8961_PWR_MGMT_1
);
reg
&=
~
WM8961_VREF
;
wm8961_write
(
codec
,
WM8961_PWR_MGMT_1
,
reg
);
/* Bias generation off */
reg
=
wm8961_read
(
codec
,
WM8961_ANTI_POP
);
reg
&=
~
(
WM8961_BUFIOEN
|
WM8961_BUFDCOPEN
);
wm8961_write
(
codec
,
WM8961_ANTI_POP
,
reg
);
/* VMID off */
reg
=
wm8961_read
(
codec
,
WM8961_PWR_MGMT_1
);
reg
&=
~
WM8961_VMIDSEL_MASK
;
wm8961_write
(
codec
,
WM8961_PWR_MGMT_1
,
reg
);
}
break
;
case
SND_SOC_BIAS_OFF
:
break
;
}
codec
->
bias_level
=
level
;
return
0
;
}
#define WM8961_RATES SNDRV_PCM_RATE_8000_48000
#define WM8961_FORMATS \
(SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
SNDRV_PCM_FMTBIT_S24_LE)
static
struct
snd_soc_dai_ops
wm8961_dai_ops
=
{
.
hw_params
=
wm8961_hw_params
,
.
set_sysclk
=
wm8961_set_sysclk
,
.
set_fmt
=
wm8961_set_fmt
,
.
digital_mute
=
wm8961_digital_mute
,
.
set_tristate
=
wm8961_set_tristate
,
.
set_clkdiv
=
wm8961_set_clkdiv
,
};
struct
snd_soc_dai
wm8961_dai
=
{
.
name
=
"WM8961"
,
.
playback
=
{
.
stream_name
=
"HiFi Playback"
,
.
channels_min
=
1
,
.
channels_max
=
2
,
.
rates
=
WM8961_RATES
,
.
formats
=
WM8961_FORMATS
,},
.
capture
=
{
.
stream_name
=
"HiFi Capture"
,
.
channels_min
=
1
,
.
channels_max
=
2
,
.
rates
=
WM8961_RATES
,
.
formats
=
WM8961_FORMATS
,},
.
ops
=
&
wm8961_dai_ops
,
};
EXPORT_SYMBOL_GPL
(
wm8961_dai
);
static
struct
snd_soc_codec
*
wm8961_codec
;
static
int
wm8961_probe
(
struct
platform_device
*
pdev
)
{
struct
snd_soc_device
*
socdev
=
platform_get_drvdata
(
pdev
);
struct
snd_soc_codec
*
codec
;
int
ret
=
0
;
if
(
wm8961_codec
==
NULL
)
{
dev_err
(
&
pdev
->
dev
,
"Codec device not registered
\n
"
);
return
-
ENODEV
;
}
socdev
->
card
->
codec
=
wm8961_codec
;
codec
=
wm8961_codec
;
/* register pcms */
ret
=
snd_soc_new_pcms
(
socdev
,
SNDRV_DEFAULT_IDX1
,
SNDRV_DEFAULT_STR1
);
if
(
ret
<
0
)
{
dev_err
(
codec
->
dev
,
"failed to create pcms: %d
\n
"
,
ret
);
goto
pcm_err
;
}
snd_soc_add_controls
(
codec
,
wm8961_snd_controls
,
ARRAY_SIZE
(
wm8961_snd_controls
));
snd_soc_dapm_new_controls
(
codec
,
wm8961_dapm_widgets
,
ARRAY_SIZE
(
wm8961_dapm_widgets
));
snd_soc_dapm_add_routes
(
codec
,
audio_paths
,
ARRAY_SIZE
(
audio_paths
));
snd_soc_dapm_new_widgets
(
codec
);
ret
=
snd_soc_init_card
(
socdev
);
if
(
ret
<
0
)
{
dev_err
(
codec
->
dev
,
"failed to register card: %d
\n
"
,
ret
);
goto
card_err
;
}
return
ret
;
card_err:
snd_soc_free_pcms
(
socdev
);
snd_soc_dapm_free
(
socdev
);
pcm_err:
return
ret
;
}
static
int
wm8961_remove
(
struct
platform_device
*
pdev
)
{
struct
snd_soc_device
*
socdev
=
platform_get_drvdata
(
pdev
);
snd_soc_free_pcms
(
socdev
);
snd_soc_dapm_free
(
socdev
);
return
0
;
}
#ifdef CONFIG_PM
static
int
wm8961_suspend
(
struct
platform_device
*
pdev
,
pm_message_t
state
)
{
struct
snd_soc_device
*
socdev
=
platform_get_drvdata
(
pdev
);
struct
snd_soc_codec
*
codec
=
socdev
->
card
->
codec
;
wm8961_set_bias_level
(
codec
,
SND_SOC_BIAS_OFF
);
return
0
;
}
static
int
wm8961_resume
(
struct
platform_device
*
pdev
)
{
struct
snd_soc_device
*
socdev
=
platform_get_drvdata
(
pdev
);
struct
snd_soc_codec
*
codec
=
socdev
->
card
->
codec
;
u16
*
reg_cache
=
codec
->
reg_cache
;
int
i
;
for
(
i
=
0
;
i
<
codec
->
reg_cache_size
;
i
++
)
{
if
(
i
==
WM8961_SOFTWARE_RESET
)
continue
;
wm8961_write
(
codec
,
i
,
reg_cache
[
i
]);
}
wm8961_set_bias_level
(
codec
,
SND_SOC_BIAS_STANDBY
);
return
0
;
}
#else
#define wm8961_suspend NULL
#define wm8961_resume NULL
#endif
struct
snd_soc_codec_device
soc_codec_dev_wm8961
=
{
.
probe
=
wm8961_probe
,
.
remove
=
wm8961_remove
,
.
suspend
=
wm8961_suspend
,
.
resume
=
wm8961_resume
,
};
EXPORT_SYMBOL_GPL
(
soc_codec_dev_wm8961
);
static
int
wm8961_register
(
struct
wm8961_priv
*
wm8961
)
{
struct
snd_soc_codec
*
codec
=
&
wm8961
->
codec
;
int
ret
;
u16
reg
;
if
(
wm8961_codec
)
{
dev_err
(
codec
->
dev
,
"Another WM8961 is registered
\n
"
);
ret
=
-
EINVAL
;
goto
err
;
}
mutex_init
(
&
codec
->
mutex
);
INIT_LIST_HEAD
(
&
codec
->
dapm_widgets
);
INIT_LIST_HEAD
(
&
codec
->
dapm_paths
);
codec
->
private_data
=
wm8961
;
codec
->
name
=
"WM8961"
;
codec
->
owner
=
THIS_MODULE
;
codec
->
read
=
wm8961_read
;
codec
->
write
=
wm8961_write
;
codec
->
dai
=
&
wm8961_dai
;
codec
->
num_dai
=
1
;
codec
->
reg_cache_size
=
ARRAY_SIZE
(
wm8961
->
reg_cache
);
codec
->
reg_cache
=
&
wm8961
->
reg_cache
;
codec
->
bias_level
=
SND_SOC_BIAS_OFF
;
codec
->
set_bias_level
=
wm8961_set_bias_level
;
memcpy
(
codec
->
reg_cache
,
wm8961_reg_defaults
,
sizeof
(
wm8961_reg_defaults
));
reg
=
wm8961_read_hw
(
codec
,
WM8961_SOFTWARE_RESET
);
if
(
reg
!=
0x1801
)
{
dev_err
(
codec
->
dev
,
"Device is not a WM8961: ID=0x%x
\n
"
,
reg
);
ret
=
-
EINVAL
;
goto
err
;
}
reg
=
wm8961_read_hw
(
codec
,
WM8961_RIGHT_INPUT_VOLUME
);
dev_info
(
codec
->
dev
,
"WM8961 family %d revision %c
\n
"
,
(
reg
&
WM8961_DEVICE_ID_MASK
)
>>
WM8961_DEVICE_ID_SHIFT
,
((
reg
&
WM8961_CHIP_REV_MASK
)
>>
WM8961_CHIP_REV_SHIFT
)
+
'A'
);
ret
=
wm8961_reset
(
codec
);
if
(
ret
<
0
)
{
dev_err
(
codec
->
dev
,
"Failed to issue reset
\n
"
);
return
ret
;
}
/* Enable class W */
reg
=
wm8961_read
(
codec
,
WM8961_CHARGE_PUMP_B
);
reg
|=
WM8961_CP_DYN_PWR_MASK
;
wm8961_write
(
codec
,
WM8961_CHARGE_PUMP_B
,
reg
);
/* Latch volume update bits (right channel only, we always
* write both out) and default ZC on. */
reg
=
wm8961_read
(
codec
,
WM8961_ROUT1_VOLUME
);
wm8961_write
(
codec
,
WM8961_ROUT1_VOLUME
,
reg
|
WM8961_LO1ZC
|
WM8961_OUT1VU
);
wm8961_write
(
codec
,
WM8961_LOUT1_VOLUME
,
reg
|
WM8961_LO1ZC
);
reg
=
wm8961_read
(
codec
,
WM8961_ROUT2_VOLUME
);
wm8961_write
(
codec
,
WM8961_ROUT2_VOLUME
,
reg
|
WM8961_SPKRZC
|
WM8961_SPKVU
);
wm8961_write
(
codec
,
WM8961_LOUT2_VOLUME
,
reg
|
WM8961_SPKLZC
);
reg
=
wm8961_read
(
codec
,
WM8961_RIGHT_ADC_VOLUME
);
wm8961_write
(
codec
,
WM8961_RIGHT_ADC_VOLUME
,
reg
|
WM8961_ADCVU
);
reg
=
wm8961_read
(
codec
,
WM8961_RIGHT_INPUT_VOLUME
);
wm8961_write
(
codec
,
WM8961_RIGHT_INPUT_VOLUME
,
reg
|
WM8961_IPVU
);
/* Use soft mute by default */
reg
=
wm8961_read
(
codec
,
WM8961_ADC_DAC_CONTROL_2
);
reg
|=
WM8961_DACSMM
;
wm8961_write
(
codec
,
WM8961_ADC_DAC_CONTROL_2
,
reg
);
/* Use automatic clocking mode by default; for now this is all
* we support.
*/
reg
=
wm8961_read
(
codec
,
WM8961_CLOCKING_3
);
reg
&=
~
WM8961_MANUAL_MODE
;
wm8961_write
(
codec
,
WM8961_CLOCKING_3
,
reg
);
wm8961_set_bias_level
(
codec
,
SND_SOC_BIAS_STANDBY
);
wm8961_dai
.
dev
=
codec
->
dev
;
wm8961_codec
=
codec
;
ret
=
snd_soc_register_codec
(
codec
);
if
(
ret
!=
0
)
{
dev_err
(
codec
->
dev
,
"Failed to register codec: %d
\n
"
,
ret
);
return
ret
;
}
ret
=
snd_soc_register_dai
(
&
wm8961_dai
);
if
(
ret
!=
0
)
{
dev_err
(
codec
->
dev
,
"Failed to register DAI: %d
\n
"
,
ret
);
snd_soc_unregister_codec
(
codec
);
return
ret
;
}
return
0
;
err:
kfree
(
wm8961
);
return
ret
;
}
static
void
wm8961_unregister
(
struct
wm8961_priv
*
wm8961
)
{
wm8961_set_bias_level
(
&
wm8961
->
codec
,
SND_SOC_BIAS_OFF
);
snd_soc_unregister_dai
(
&
wm8961_dai
);
snd_soc_unregister_codec
(
&
wm8961
->
codec
);
kfree
(
wm8961
);
wm8961_codec
=
NULL
;
}
static
__devinit
int
wm8961_i2c_probe
(
struct
i2c_client
*
i2c
,
const
struct
i2c_device_id
*
id
)
{
struct
wm8961_priv
*
wm8961
;
struct
snd_soc_codec
*
codec
;
wm8961
=
kzalloc
(
sizeof
(
struct
wm8961_priv
),
GFP_KERNEL
);
if
(
wm8961
==
NULL
)
return
-
ENOMEM
;
codec
=
&
wm8961
->
codec
;
codec
->
hw_write
=
(
hw_write_t
)
i2c_master_send
;
i2c_set_clientdata
(
i2c
,
wm8961
);
codec
->
control_data
=
i2c
;
codec
->
dev
=
&
i2c
->
dev
;
return
wm8961_register
(
wm8961
);
}
static
__devexit
int
wm8961_i2c_remove
(
struct
i2c_client
*
client
)
{
struct
wm8961_priv
*
wm8961
=
i2c_get_clientdata
(
client
);
wm8961_unregister
(
wm8961
);
return
0
;
}
static
const
struct
i2c_device_id
wm8961_i2c_id
[]
=
{
{
"wm8961"
,
0
},
{
}
};
MODULE_DEVICE_TABLE
(
i2c
,
wm8961_i2c_id
);
static
struct
i2c_driver
wm8961_i2c_driver
=
{
.
driver
=
{
.
name
=
"wm8961"
,
.
owner
=
THIS_MODULE
,
},
.
probe
=
wm8961_i2c_probe
,
.
remove
=
__devexit_p
(
wm8961_i2c_remove
),
.
id_table
=
wm8961_i2c_id
,
};
static
int
__init
wm8961_modinit
(
void
)
{
int
ret
;
ret
=
i2c_add_driver
(
&
wm8961_i2c_driver
);
if
(
ret
!=
0
)
{
printk
(
KERN_ERR
"Failed to register WM8961 I2C driver: %d
\n
"
,
ret
);
}
return
ret
;
}
module_init
(
wm8961_modinit
);
static
void
__exit
wm8961_exit
(
void
)
{
i2c_del_driver
(
&
wm8961_i2c_driver
);
}
module_exit
(
wm8961_exit
);
MODULE_DESCRIPTION
(
"ASoC WM8961 driver"
);
MODULE_AUTHOR
(
"Mark Brown <broonie@opensource.wolfsonmicro.com>"
);
MODULE_LICENSE
(
"GPL"
);
sound/soc/codecs/wm8961.h
0 → 100644
View file @
e370f45a
/*
* wm8961.h -- WM8961 Soc Audio driver
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef _WM8961_H
#define _WM8961_H
#include <sound/soc.h>
extern
struct
snd_soc_codec_device
soc_codec_dev_wm8961
;
extern
struct
snd_soc_dai
wm8961_dai
;
#define WM8961_BCLK 1
#define WM8961_LRCLK 2
#define WM8961_BCLK_DIV_1 0
#define WM8961_BCLK_DIV_1_5 1
#define WM8961_BCLK_DIV_2 2
#define WM8961_BCLK_DIV_3 3
#define WM8961_BCLK_DIV_4 4
#define WM8961_BCLK_DIV_5_5 5
#define WM8961_BCLK_DIV_6 6
#define WM8961_BCLK_DIV_8 7
#define WM8961_BCLK_DIV_11 8
#define WM8961_BCLK_DIV_12 9
#define WM8961_BCLK_DIV_16 10
#define WM8961_BCLK_DIV_24 11
#define WM8961_BCLK_DIV_32 13
/*
* Register values.
*/
#define WM8961_LEFT_INPUT_VOLUME 0x00
#define WM8961_RIGHT_INPUT_VOLUME 0x01
#define WM8961_LOUT1_VOLUME 0x02
#define WM8961_ROUT1_VOLUME 0x03
#define WM8961_CLOCKING1 0x04
#define WM8961_ADC_DAC_CONTROL_1 0x05
#define WM8961_ADC_DAC_CONTROL_2 0x06
#define WM8961_AUDIO_INTERFACE_0 0x07
#define WM8961_CLOCKING2 0x08
#define WM8961_AUDIO_INTERFACE_1 0x09
#define WM8961_LEFT_DAC_VOLUME 0x0A
#define WM8961_RIGHT_DAC_VOLUME 0x0B
#define WM8961_AUDIO_INTERFACE_2 0x0E
#define WM8961_SOFTWARE_RESET 0x0F
#define WM8961_ALC1 0x11
#define WM8961_ALC2 0x12
#define WM8961_ALC3 0x13
#define WM8961_NOISE_GATE 0x14
#define WM8961_LEFT_ADC_VOLUME 0x15
#define WM8961_RIGHT_ADC_VOLUME 0x16
#define WM8961_ADDITIONAL_CONTROL_1 0x17
#define WM8961_ADDITIONAL_CONTROL_2 0x18
#define WM8961_PWR_MGMT_1 0x19
#define WM8961_PWR_MGMT_2 0x1A
#define WM8961_ADDITIONAL_CONTROL_3 0x1B
#define WM8961_ANTI_POP 0x1C
#define WM8961_CLOCKING_3 0x1E
#define WM8961_ADCL_SIGNAL_PATH 0x20
#define WM8961_ADCR_SIGNAL_PATH 0x21
#define WM8961_LOUT2_VOLUME 0x28
#define WM8961_ROUT2_VOLUME 0x29
#define WM8961_PWR_MGMT_3 0x2F
#define WM8961_ADDITIONAL_CONTROL_4 0x30
#define WM8961_CLASS_D_CONTROL_1 0x31
#define WM8961_CLASS_D_CONTROL_2 0x33
#define WM8961_CLOCKING_4 0x38
#define WM8961_DSP_SIDETONE_0 0x39
#define WM8961_DSP_SIDETONE_1 0x3A
#define WM8961_DC_SERVO_0 0x3C
#define WM8961_DC_SERVO_1 0x3D
#define WM8961_DC_SERVO_3 0x3F
#define WM8961_DC_SERVO_5 0x41
#define WM8961_ANALOGUE_PGA_BIAS 0x44
#define WM8961_ANALOGUE_HP_0 0x45
#define WM8961_ANALOGUE_HP_2 0x47
#define WM8961_CHARGE_PUMP_1 0x48
#define WM8961_CHARGE_PUMP_B 0x52
#define WM8961_WRITE_SEQUENCER_1 0x57
#define WM8961_WRITE_SEQUENCER_2 0x58
#define WM8961_WRITE_SEQUENCER_3 0x59
#define WM8961_WRITE_SEQUENCER_4 0x5A
#define WM8961_WRITE_SEQUENCER_5 0x5B
#define WM8961_WRITE_SEQUENCER_6 0x5C
#define WM8961_WRITE_SEQUENCER_7 0x5D
#define WM8961_GENERAL_TEST_1 0xFC
/*
* Field Definitions.
*/
/*
* R0 (0x00) - Left Input volume
*/
#define WM8961_IPVU 0x0100
/* IPVU */
#define WM8961_IPVU_MASK 0x0100
/* IPVU */
#define WM8961_IPVU_SHIFT 8
/* IPVU */
#define WM8961_IPVU_WIDTH 1
/* IPVU */
#define WM8961_LINMUTE 0x0080
/* LINMUTE */
#define WM8961_LINMUTE_MASK 0x0080
/* LINMUTE */
#define WM8961_LINMUTE_SHIFT 7
/* LINMUTE */
#define WM8961_LINMUTE_WIDTH 1
/* LINMUTE */
#define WM8961_LIZC 0x0040
/* LIZC */
#define WM8961_LIZC_MASK 0x0040
/* LIZC */
#define WM8961_LIZC_SHIFT 6
/* LIZC */
#define WM8961_LIZC_WIDTH 1
/* LIZC */
#define WM8961_LINVOL_MASK 0x003F
/* LINVOL - [5:0] */
#define WM8961_LINVOL_SHIFT 0
/* LINVOL - [5:0] */
#define WM8961_LINVOL_WIDTH 6
/* LINVOL - [5:0] */
/*
* R1 (0x01) - Right Input volume
*/
#define WM8961_DEVICE_ID_MASK 0xF000
/* DEVICE_ID - [15:12] */
#define WM8961_DEVICE_ID_SHIFT 12
/* DEVICE_ID - [15:12] */
#define WM8961_DEVICE_ID_WIDTH 4
/* DEVICE_ID - [15:12] */
#define WM8961_CHIP_REV_MASK 0x0E00
/* CHIP_REV - [11:9] */
#define WM8961_CHIP_REV_SHIFT 9
/* CHIP_REV - [11:9] */
#define WM8961_CHIP_REV_WIDTH 3
/* CHIP_REV - [11:9] */
#define WM8961_IPVU 0x0100
/* IPVU */
#define WM8961_IPVU_MASK 0x0100
/* IPVU */
#define WM8961_IPVU_SHIFT 8
/* IPVU */
#define WM8961_IPVU_WIDTH 1
/* IPVU */
#define WM8961_RINMUTE 0x0080
/* RINMUTE */
#define WM8961_RINMUTE_MASK 0x0080
/* RINMUTE */
#define WM8961_RINMUTE_SHIFT 7
/* RINMUTE */
#define WM8961_RINMUTE_WIDTH 1
/* RINMUTE */
#define WM8961_RIZC 0x0040
/* RIZC */
#define WM8961_RIZC_MASK 0x0040
/* RIZC */
#define WM8961_RIZC_SHIFT 6
/* RIZC */
#define WM8961_RIZC_WIDTH 1
/* RIZC */
#define WM8961_RINVOL_MASK 0x003F
/* RINVOL - [5:0] */
#define WM8961_RINVOL_SHIFT 0
/* RINVOL - [5:0] */
#define WM8961_RINVOL_WIDTH 6
/* RINVOL - [5:0] */
/*
* R2 (0x02) - LOUT1 volume
*/
#define WM8961_OUT1VU 0x0100
/* OUT1VU */
#define WM8961_OUT1VU_MASK 0x0100
/* OUT1VU */
#define WM8961_OUT1VU_SHIFT 8
/* OUT1VU */
#define WM8961_OUT1VU_WIDTH 1
/* OUT1VU */
#define WM8961_LO1ZC 0x0080
/* LO1ZC */
#define WM8961_LO1ZC_MASK 0x0080
/* LO1ZC */
#define WM8961_LO1ZC_SHIFT 7
/* LO1ZC */
#define WM8961_LO1ZC_WIDTH 1
/* LO1ZC */
#define WM8961_LOUT1VOL_MASK 0x007F
/* LOUT1VOL - [6:0] */
#define WM8961_LOUT1VOL_SHIFT 0
/* LOUT1VOL - [6:0] */
#define WM8961_LOUT1VOL_WIDTH 7
/* LOUT1VOL - [6:0] */
/*
* R3 (0x03) - ROUT1 volume
*/
#define WM8961_OUT1VU 0x0100
/* OUT1VU */
#define WM8961_OUT1VU_MASK 0x0100
/* OUT1VU */
#define WM8961_OUT1VU_SHIFT 8
/* OUT1VU */
#define WM8961_OUT1VU_WIDTH 1
/* OUT1VU */
#define WM8961_RO1ZC 0x0080
/* RO1ZC */
#define WM8961_RO1ZC_MASK 0x0080
/* RO1ZC */
#define WM8961_RO1ZC_SHIFT 7
/* RO1ZC */
#define WM8961_RO1ZC_WIDTH 1
/* RO1ZC */
#define WM8961_ROUT1VOL_MASK 0x007F
/* ROUT1VOL - [6:0] */
#define WM8961_ROUT1VOL_SHIFT 0
/* ROUT1VOL - [6:0] */
#define WM8961_ROUT1VOL_WIDTH 7
/* ROUT1VOL - [6:0] */
/*
* R4 (0x04) - Clocking1
*/
#define WM8961_ADCDIV_MASK 0x01C0
/* ADCDIV - [8:6] */
#define WM8961_ADCDIV_SHIFT 6
/* ADCDIV - [8:6] */
#define WM8961_ADCDIV_WIDTH 3
/* ADCDIV - [8:6] */
#define WM8961_DACDIV_MASK 0x0038
/* DACDIV - [5:3] */
#define WM8961_DACDIV_SHIFT 3
/* DACDIV - [5:3] */
#define WM8961_DACDIV_WIDTH 3
/* DACDIV - [5:3] */
#define WM8961_MCLKDIV 0x0004
/* MCLKDIV */
#define WM8961_MCLKDIV_MASK 0x0004
/* MCLKDIV */
#define WM8961_MCLKDIV_SHIFT 2
/* MCLKDIV */
#define WM8961_MCLKDIV_WIDTH 1
/* MCLKDIV */
/*
* R5 (0x05) - ADC & DAC Control 1
*/
#define WM8961_ADCPOL_MASK 0x0060
/* ADCPOL - [6:5] */
#define WM8961_ADCPOL_SHIFT 5
/* ADCPOL - [6:5] */
#define WM8961_ADCPOL_WIDTH 2
/* ADCPOL - [6:5] */
#define WM8961_DACMU 0x0008
/* DACMU */
#define WM8961_DACMU_MASK 0x0008
/* DACMU */
#define WM8961_DACMU_SHIFT 3
/* DACMU */
#define WM8961_DACMU_WIDTH 1
/* DACMU */
#define WM8961_DEEMPH_MASK 0x0006
/* DEEMPH - [2:1] */
#define WM8961_DEEMPH_SHIFT 1
/* DEEMPH - [2:1] */
#define WM8961_DEEMPH_WIDTH 2
/* DEEMPH - [2:1] */
#define WM8961_ADCHPD 0x0001
/* ADCHPD */
#define WM8961_ADCHPD_MASK 0x0001
/* ADCHPD */
#define WM8961_ADCHPD_SHIFT 0
/* ADCHPD */
#define WM8961_ADCHPD_WIDTH 1
/* ADCHPD */
/*
* R6 (0x06) - ADC & DAC Control 2
*/
#define WM8961_ADC_HPF_CUT_MASK 0x0180
/* ADC_HPF_CUT - [8:7] */
#define WM8961_ADC_HPF_CUT_SHIFT 7
/* ADC_HPF_CUT - [8:7] */
#define WM8961_ADC_HPF_CUT_WIDTH 2
/* ADC_HPF_CUT - [8:7] */
#define WM8961_DACPOL_MASK 0x0060
/* DACPOL - [6:5] */
#define WM8961_DACPOL_SHIFT 5
/* DACPOL - [6:5] */
#define WM8961_DACPOL_WIDTH 2
/* DACPOL - [6:5] */
#define WM8961_DACSMM 0x0008
/* DACSMM */
#define WM8961_DACSMM_MASK 0x0008
/* DACSMM */
#define WM8961_DACSMM_SHIFT 3
/* DACSMM */
#define WM8961_DACSMM_WIDTH 1
/* DACSMM */
#define WM8961_DACMR 0x0004
/* DACMR */
#define WM8961_DACMR_MASK 0x0004
/* DACMR */
#define WM8961_DACMR_SHIFT 2
/* DACMR */
#define WM8961_DACMR_WIDTH 1
/* DACMR */
#define WM8961_DACSLOPE 0x0002
/* DACSLOPE */
#define WM8961_DACSLOPE_MASK 0x0002
/* DACSLOPE */
#define WM8961_DACSLOPE_SHIFT 1
/* DACSLOPE */
#define WM8961_DACSLOPE_WIDTH 1
/* DACSLOPE */
#define WM8961_DAC_OSR128 0x0001
/* DAC_OSR128 */
#define WM8961_DAC_OSR128_MASK 0x0001
/* DAC_OSR128 */
#define WM8961_DAC_OSR128_SHIFT 0
/* DAC_OSR128 */
#define WM8961_DAC_OSR128_WIDTH 1
/* DAC_OSR128 */
/*
* R7 (0x07) - Audio Interface 0
*/
#define WM8961_ALRSWAP 0x0100
/* ALRSWAP */
#define WM8961_ALRSWAP_MASK 0x0100
/* ALRSWAP */
#define WM8961_ALRSWAP_SHIFT 8
/* ALRSWAP */
#define WM8961_ALRSWAP_WIDTH 1
/* ALRSWAP */
#define WM8961_BCLKINV 0x0080
/* BCLKINV */
#define WM8961_BCLKINV_MASK 0x0080
/* BCLKINV */
#define WM8961_BCLKINV_SHIFT 7
/* BCLKINV */
#define WM8961_BCLKINV_WIDTH 1
/* BCLKINV */
#define WM8961_MS 0x0040
/* MS */
#define WM8961_MS_MASK 0x0040
/* MS */
#define WM8961_MS_SHIFT 6
/* MS */
#define WM8961_MS_WIDTH 1
/* MS */
#define WM8961_DLRSWAP 0x0020
/* DLRSWAP */
#define WM8961_DLRSWAP_MASK 0x0020
/* DLRSWAP */
#define WM8961_DLRSWAP_SHIFT 5
/* DLRSWAP */
#define WM8961_DLRSWAP_WIDTH 1
/* DLRSWAP */
#define WM8961_LRP 0x0010
/* LRP */
#define WM8961_LRP_MASK 0x0010
/* LRP */
#define WM8961_LRP_SHIFT 4
/* LRP */
#define WM8961_LRP_WIDTH 1
/* LRP */
#define WM8961_WL_MASK 0x000C
/* WL - [3:2] */
#define WM8961_WL_SHIFT 2
/* WL - [3:2] */
#define WM8961_WL_WIDTH 2
/* WL - [3:2] */
#define WM8961_FORMAT_MASK 0x0003
/* FORMAT - [1:0] */
#define WM8961_FORMAT_SHIFT 0
/* FORMAT - [1:0] */
#define WM8961_FORMAT_WIDTH 2
/* FORMAT - [1:0] */
/*
* R8 (0x08) - Clocking2
*/
#define WM8961_DCLKDIV_MASK 0x01C0
/* DCLKDIV - [8:6] */
#define WM8961_DCLKDIV_SHIFT 6
/* DCLKDIV - [8:6] */
#define WM8961_DCLKDIV_WIDTH 3
/* DCLKDIV - [8:6] */
#define WM8961_CLK_SYS_ENA 0x0020
/* CLK_SYS_ENA */
#define WM8961_CLK_SYS_ENA_MASK 0x0020
/* CLK_SYS_ENA */
#define WM8961_CLK_SYS_ENA_SHIFT 5
/* CLK_SYS_ENA */
#define WM8961_CLK_SYS_ENA_WIDTH 1
/* CLK_SYS_ENA */
#define WM8961_CLK_DSP_ENA 0x0010
/* CLK_DSP_ENA */
#define WM8961_CLK_DSP_ENA_MASK 0x0010
/* CLK_DSP_ENA */
#define WM8961_CLK_DSP_ENA_SHIFT 4
/* CLK_DSP_ENA */
#define WM8961_CLK_DSP_ENA_WIDTH 1
/* CLK_DSP_ENA */
#define WM8961_BCLKDIV_MASK 0x000F
/* BCLKDIV - [3:0] */
#define WM8961_BCLKDIV_SHIFT 0
/* BCLKDIV - [3:0] */
#define WM8961_BCLKDIV_WIDTH 4
/* BCLKDIV - [3:0] */
/*
* R9 (0x09) - Audio Interface 1
*/
#define WM8961_DACCOMP_MASK 0x0018
/* DACCOMP - [4:3] */
#define WM8961_DACCOMP_SHIFT 3
/* DACCOMP - [4:3] */
#define WM8961_DACCOMP_WIDTH 2
/* DACCOMP - [4:3] */
#define WM8961_ADCCOMP_MASK 0x0006
/* ADCCOMP - [2:1] */
#define WM8961_ADCCOMP_SHIFT 1
/* ADCCOMP - [2:1] */
#define WM8961_ADCCOMP_WIDTH 2
/* ADCCOMP - [2:1] */
#define WM8961_LOOPBACK 0x0001
/* LOOPBACK */
#define WM8961_LOOPBACK_MASK 0x0001
/* LOOPBACK */
#define WM8961_LOOPBACK_SHIFT 0
/* LOOPBACK */
#define WM8961_LOOPBACK_WIDTH 1
/* LOOPBACK */
/*
* R10 (0x0A) - Left DAC volume
*/
#define WM8961_DACVU 0x0100
/* DACVU */
#define WM8961_DACVU_MASK 0x0100
/* DACVU */
#define WM8961_DACVU_SHIFT 8
/* DACVU */
#define WM8961_DACVU_WIDTH 1
/* DACVU */
#define WM8961_LDACVOL_MASK 0x00FF
/* LDACVOL - [7:0] */
#define WM8961_LDACVOL_SHIFT 0
/* LDACVOL - [7:0] */
#define WM8961_LDACVOL_WIDTH 8
/* LDACVOL - [7:0] */
/*
* R11 (0x0B) - Right DAC volume
*/
#define WM8961_DACVU 0x0100
/* DACVU */
#define WM8961_DACVU_MASK 0x0100
/* DACVU */
#define WM8961_DACVU_SHIFT 8
/* DACVU */
#define WM8961_DACVU_WIDTH 1
/* DACVU */
#define WM8961_RDACVOL_MASK 0x00FF
/* RDACVOL - [7:0] */
#define WM8961_RDACVOL_SHIFT 0
/* RDACVOL - [7:0] */
#define WM8961_RDACVOL_WIDTH 8
/* RDACVOL - [7:0] */
/*
* R14 (0x0E) - Audio Interface 2
*/
#define WM8961_LRCLK_RATE_MASK 0x01FF
/* LRCLK_RATE - [8:0] */
#define WM8961_LRCLK_RATE_SHIFT 0
/* LRCLK_RATE - [8:0] */
#define WM8961_LRCLK_RATE_WIDTH 9
/* LRCLK_RATE - [8:0] */
/*
* R15 (0x0F) - Software Reset
*/
#define WM8961_SW_RST_DEV_ID1_MASK 0xFFFF
/* SW_RST_DEV_ID1 - [15:0] */
#define WM8961_SW_RST_DEV_ID1_SHIFT 0
/* SW_RST_DEV_ID1 - [15:0] */
#define WM8961_SW_RST_DEV_ID1_WIDTH 16
/* SW_RST_DEV_ID1 - [15:0] */
/*
* R17 (0x11) - ALC1
*/
#define WM8961_ALCSEL_MASK 0x0180
/* ALCSEL - [8:7] */
#define WM8961_ALCSEL_SHIFT 7
/* ALCSEL - [8:7] */
#define WM8961_ALCSEL_WIDTH 2
/* ALCSEL - [8:7] */
#define WM8961_MAXGAIN_MASK 0x0070
/* MAXGAIN - [6:4] */
#define WM8961_MAXGAIN_SHIFT 4
/* MAXGAIN - [6:4] */
#define WM8961_MAXGAIN_WIDTH 3
/* MAXGAIN - [6:4] */
#define WM8961_ALCL_MASK 0x000F
/* ALCL - [3:0] */
#define WM8961_ALCL_SHIFT 0
/* ALCL - [3:0] */
#define WM8961_ALCL_WIDTH 4
/* ALCL - [3:0] */
/*
* R18 (0x12) - ALC2
*/
#define WM8961_ALCZC 0x0080
/* ALCZC */
#define WM8961_ALCZC_MASK 0x0080
/* ALCZC */
#define WM8961_ALCZC_SHIFT 7
/* ALCZC */
#define WM8961_ALCZC_WIDTH 1
/* ALCZC */
#define WM8961_MINGAIN_MASK 0x0070
/* MINGAIN - [6:4] */
#define WM8961_MINGAIN_SHIFT 4
/* MINGAIN - [6:4] */
#define WM8961_MINGAIN_WIDTH 3
/* MINGAIN - [6:4] */
#define WM8961_HLD_MASK 0x000F
/* HLD - [3:0] */
#define WM8961_HLD_SHIFT 0
/* HLD - [3:0] */
#define WM8961_HLD_WIDTH 4
/* HLD - [3:0] */
/*
* R19 (0x13) - ALC3
*/
#define WM8961_ALCMODE 0x0100
/* ALCMODE */
#define WM8961_ALCMODE_MASK 0x0100
/* ALCMODE */
#define WM8961_ALCMODE_SHIFT 8
/* ALCMODE */
#define WM8961_ALCMODE_WIDTH 1
/* ALCMODE */
#define WM8961_DCY_MASK 0x00F0
/* DCY - [7:4] */
#define WM8961_DCY_SHIFT 4
/* DCY - [7:4] */
#define WM8961_DCY_WIDTH 4
/* DCY - [7:4] */
#define WM8961_ATK_MASK 0x000F
/* ATK - [3:0] */
#define WM8961_ATK_SHIFT 0
/* ATK - [3:0] */
#define WM8961_ATK_WIDTH 4
/* ATK - [3:0] */
/*
* R20 (0x14) - Noise Gate
*/
#define WM8961_NGTH_MASK 0x00F8
/* NGTH - [7:3] */
#define WM8961_NGTH_SHIFT 3
/* NGTH - [7:3] */
#define WM8961_NGTH_WIDTH 5
/* NGTH - [7:3] */
#define WM8961_NGG 0x0002
/* NGG */
#define WM8961_NGG_MASK 0x0002
/* NGG */
#define WM8961_NGG_SHIFT 1
/* NGG */
#define WM8961_NGG_WIDTH 1
/* NGG */
#define WM8961_NGAT 0x0001
/* NGAT */
#define WM8961_NGAT_MASK 0x0001
/* NGAT */
#define WM8961_NGAT_SHIFT 0
/* NGAT */
#define WM8961_NGAT_WIDTH 1
/* NGAT */
/*
* R21 (0x15) - Left ADC volume
*/
#define WM8961_ADCVU 0x0100
/* ADCVU */
#define WM8961_ADCVU_MASK 0x0100
/* ADCVU */
#define WM8961_ADCVU_SHIFT 8
/* ADCVU */
#define WM8961_ADCVU_WIDTH 1
/* ADCVU */
#define WM8961_LADCVOL_MASK 0x00FF
/* LADCVOL - [7:0] */
#define WM8961_LADCVOL_SHIFT 0
/* LADCVOL - [7:0] */
#define WM8961_LADCVOL_WIDTH 8
/* LADCVOL - [7:0] */
/*
* R22 (0x16) - Right ADC volume
*/
#define WM8961_ADCVU 0x0100
/* ADCVU */
#define WM8961_ADCVU_MASK 0x0100
/* ADCVU */
#define WM8961_ADCVU_SHIFT 8
/* ADCVU */
#define WM8961_ADCVU_WIDTH 1
/* ADCVU */
#define WM8961_RADCVOL_MASK 0x00FF
/* RADCVOL - [7:0] */
#define WM8961_RADCVOL_SHIFT 0
/* RADCVOL - [7:0] */
#define WM8961_RADCVOL_WIDTH 8
/* RADCVOL - [7:0] */
/*
* R23 (0x17) - Additional control(1)
*/
#define WM8961_TSDEN 0x0100
/* TSDEN */
#define WM8961_TSDEN_MASK 0x0100
/* TSDEN */
#define WM8961_TSDEN_SHIFT 8
/* TSDEN */
#define WM8961_TSDEN_WIDTH 1
/* TSDEN */
#define WM8961_DMONOMIX 0x0010
/* DMONOMIX */
#define WM8961_DMONOMIX_MASK 0x0010
/* DMONOMIX */
#define WM8961_DMONOMIX_SHIFT 4
/* DMONOMIX */
#define WM8961_DMONOMIX_WIDTH 1
/* DMONOMIX */
#define WM8961_TOEN 0x0001
/* TOEN */
#define WM8961_TOEN_MASK 0x0001
/* TOEN */
#define WM8961_TOEN_SHIFT 0
/* TOEN */
#define WM8961_TOEN_WIDTH 1
/* TOEN */
/*
* R24 (0x18) - Additional control(2)
*/
#define WM8961_TRIS 0x0008
/* TRIS */
#define WM8961_TRIS_MASK 0x0008
/* TRIS */
#define WM8961_TRIS_SHIFT 3
/* TRIS */
#define WM8961_TRIS_WIDTH 1
/* TRIS */
/*
* R25 (0x19) - Pwr Mgmt (1)
*/
#define WM8961_VMIDSEL_MASK 0x0180
/* VMIDSEL - [8:7] */
#define WM8961_VMIDSEL_SHIFT 7
/* VMIDSEL - [8:7] */
#define WM8961_VMIDSEL_WIDTH 2
/* VMIDSEL - [8:7] */
#define WM8961_VREF 0x0040
/* VREF */
#define WM8961_VREF_MASK 0x0040
/* VREF */
#define WM8961_VREF_SHIFT 6
/* VREF */
#define WM8961_VREF_WIDTH 1
/* VREF */
#define WM8961_AINL 0x0020
/* AINL */
#define WM8961_AINL_MASK 0x0020
/* AINL */
#define WM8961_AINL_SHIFT 5
/* AINL */
#define WM8961_AINL_WIDTH 1
/* AINL */
#define WM8961_AINR 0x0010
/* AINR */
#define WM8961_AINR_MASK 0x0010
/* AINR */
#define WM8961_AINR_SHIFT 4
/* AINR */
#define WM8961_AINR_WIDTH 1
/* AINR */
#define WM8961_ADCL 0x0008
/* ADCL */
#define WM8961_ADCL_MASK 0x0008
/* ADCL */
#define WM8961_ADCL_SHIFT 3
/* ADCL */
#define WM8961_ADCL_WIDTH 1
/* ADCL */
#define WM8961_ADCR 0x0004
/* ADCR */
#define WM8961_ADCR_MASK 0x0004
/* ADCR */
#define WM8961_ADCR_SHIFT 2
/* ADCR */
#define WM8961_ADCR_WIDTH 1
/* ADCR */
#define WM8961_MICB 0x0002
/* MICB */
#define WM8961_MICB_MASK 0x0002
/* MICB */
#define WM8961_MICB_SHIFT 1
/* MICB */
#define WM8961_MICB_WIDTH 1
/* MICB */
/*
* R26 (0x1A) - Pwr Mgmt (2)
*/
#define WM8961_DACL 0x0100
/* DACL */
#define WM8961_DACL_MASK 0x0100
/* DACL */
#define WM8961_DACL_SHIFT 8
/* DACL */
#define WM8961_DACL_WIDTH 1
/* DACL */
#define WM8961_DACR 0x0080
/* DACR */
#define WM8961_DACR_MASK 0x0080
/* DACR */
#define WM8961_DACR_SHIFT 7
/* DACR */
#define WM8961_DACR_WIDTH 1
/* DACR */
#define WM8961_LOUT1_PGA 0x0040
/* LOUT1_PGA */
#define WM8961_LOUT1_PGA_MASK 0x0040
/* LOUT1_PGA */
#define WM8961_LOUT1_PGA_SHIFT 6
/* LOUT1_PGA */
#define WM8961_LOUT1_PGA_WIDTH 1
/* LOUT1_PGA */
#define WM8961_ROUT1_PGA 0x0020
/* ROUT1_PGA */
#define WM8961_ROUT1_PGA_MASK 0x0020
/* ROUT1_PGA */
#define WM8961_ROUT1_PGA_SHIFT 5
/* ROUT1_PGA */
#define WM8961_ROUT1_PGA_WIDTH 1
/* ROUT1_PGA */
#define WM8961_SPKL_PGA 0x0010
/* SPKL_PGA */
#define WM8961_SPKL_PGA_MASK 0x0010
/* SPKL_PGA */
#define WM8961_SPKL_PGA_SHIFT 4
/* SPKL_PGA */
#define WM8961_SPKL_PGA_WIDTH 1
/* SPKL_PGA */
#define WM8961_SPKR_PGA 0x0008
/* SPKR_PGA */
#define WM8961_SPKR_PGA_MASK 0x0008
/* SPKR_PGA */
#define WM8961_SPKR_PGA_SHIFT 3
/* SPKR_PGA */
#define WM8961_SPKR_PGA_WIDTH 1
/* SPKR_PGA */
/*
* R27 (0x1B) - Additional Control (3)
*/
#define WM8961_SAMPLE_RATE_MASK 0x0007
/* SAMPLE_RATE - [2:0] */
#define WM8961_SAMPLE_RATE_SHIFT 0
/* SAMPLE_RATE - [2:0] */
#define WM8961_SAMPLE_RATE_WIDTH 3
/* SAMPLE_RATE - [2:0] */
/*
* R28 (0x1C) - Anti-pop
*/
#define WM8961_BUFDCOPEN 0x0010
/* BUFDCOPEN */
#define WM8961_BUFDCOPEN_MASK 0x0010
/* BUFDCOPEN */
#define WM8961_BUFDCOPEN_SHIFT 4
/* BUFDCOPEN */
#define WM8961_BUFDCOPEN_WIDTH 1
/* BUFDCOPEN */
#define WM8961_BUFIOEN 0x0008
/* BUFIOEN */
#define WM8961_BUFIOEN_MASK 0x0008
/* BUFIOEN */
#define WM8961_BUFIOEN_SHIFT 3
/* BUFIOEN */
#define WM8961_BUFIOEN_WIDTH 1
/* BUFIOEN */
#define WM8961_SOFT_ST 0x0004
/* SOFT_ST */
#define WM8961_SOFT_ST_MASK 0x0004
/* SOFT_ST */
#define WM8961_SOFT_ST_SHIFT 2
/* SOFT_ST */
#define WM8961_SOFT_ST_WIDTH 1
/* SOFT_ST */
/*
* R30 (0x1E) - Clocking 3
*/
#define WM8961_CLK_TO_DIV_MASK 0x0180
/* CLK_TO_DIV - [8:7] */
#define WM8961_CLK_TO_DIV_SHIFT 7
/* CLK_TO_DIV - [8:7] */
#define WM8961_CLK_TO_DIV_WIDTH 2
/* CLK_TO_DIV - [8:7] */
#define WM8961_CLK_256K_DIV_MASK 0x007E
/* CLK_256K_DIV - [6:1] */
#define WM8961_CLK_256K_DIV_SHIFT 1
/* CLK_256K_DIV - [6:1] */
#define WM8961_CLK_256K_DIV_WIDTH 6
/* CLK_256K_DIV - [6:1] */
#define WM8961_MANUAL_MODE 0x0001
/* MANUAL_MODE */
#define WM8961_MANUAL_MODE_MASK 0x0001
/* MANUAL_MODE */
#define WM8961_MANUAL_MODE_SHIFT 0
/* MANUAL_MODE */
#define WM8961_MANUAL_MODE_WIDTH 1
/* MANUAL_MODE */
/*
* R32 (0x20) - ADCL signal path
*/
#define WM8961_LMICBOOST_MASK 0x0030
/* LMICBOOST - [5:4] */
#define WM8961_LMICBOOST_SHIFT 4
/* LMICBOOST - [5:4] */
#define WM8961_LMICBOOST_WIDTH 2
/* LMICBOOST - [5:4] */
/*
* R33 (0x21) - ADCR signal path
*/
#define WM8961_RMICBOOST_MASK 0x0030
/* RMICBOOST - [5:4] */
#define WM8961_RMICBOOST_SHIFT 4
/* RMICBOOST - [5:4] */
#define WM8961_RMICBOOST_WIDTH 2
/* RMICBOOST - [5:4] */
/*
* R40 (0x28) - LOUT2 volume
*/
#define WM8961_SPKVU 0x0100
/* SPKVU */
#define WM8961_SPKVU_MASK 0x0100
/* SPKVU */
#define WM8961_SPKVU_SHIFT 8
/* SPKVU */
#define WM8961_SPKVU_WIDTH 1
/* SPKVU */
#define WM8961_SPKLZC 0x0080
/* SPKLZC */
#define WM8961_SPKLZC_MASK 0x0080
/* SPKLZC */
#define WM8961_SPKLZC_SHIFT 7
/* SPKLZC */
#define WM8961_SPKLZC_WIDTH 1
/* SPKLZC */
#define WM8961_SPKLVOL_MASK 0x007F
/* SPKLVOL - [6:0] */
#define WM8961_SPKLVOL_SHIFT 0
/* SPKLVOL - [6:0] */
#define WM8961_SPKLVOL_WIDTH 7
/* SPKLVOL - [6:0] */
/*
* R41 (0x29) - ROUT2 volume
*/
#define WM8961_SPKVU 0x0100
/* SPKVU */
#define WM8961_SPKVU_MASK 0x0100
/* SPKVU */
#define WM8961_SPKVU_SHIFT 8
/* SPKVU */
#define WM8961_SPKVU_WIDTH 1
/* SPKVU */
#define WM8961_SPKRZC 0x0080
/* SPKRZC */
#define WM8961_SPKRZC_MASK 0x0080
/* SPKRZC */
#define WM8961_SPKRZC_SHIFT 7
/* SPKRZC */
#define WM8961_SPKRZC_WIDTH 1
/* SPKRZC */
#define WM8961_SPKRVOL_MASK 0x007F
/* SPKRVOL - [6:0] */
#define WM8961_SPKRVOL_SHIFT 0
/* SPKRVOL - [6:0] */
#define WM8961_SPKRVOL_WIDTH 7
/* SPKRVOL - [6:0] */
/*
* R47 (0x2F) - Pwr Mgmt (3)
*/
#define WM8961_TEMP_SHUT 0x0002
/* TEMP_SHUT */
#define WM8961_TEMP_SHUT_MASK 0x0002
/* TEMP_SHUT */
#define WM8961_TEMP_SHUT_SHIFT 1
/* TEMP_SHUT */
#define WM8961_TEMP_SHUT_WIDTH 1
/* TEMP_SHUT */
#define WM8961_TEMP_WARN 0x0001
/* TEMP_WARN */
#define WM8961_TEMP_WARN_MASK 0x0001
/* TEMP_WARN */
#define WM8961_TEMP_WARN_SHIFT 0
/* TEMP_WARN */
#define WM8961_TEMP_WARN_WIDTH 1
/* TEMP_WARN */
/*
* R48 (0x30) - Additional Control (4)
*/
#define WM8961_TSENSEN 0x0002
/* TSENSEN */
#define WM8961_TSENSEN_MASK 0x0002
/* TSENSEN */
#define WM8961_TSENSEN_SHIFT 1
/* TSENSEN */
#define WM8961_TSENSEN_WIDTH 1
/* TSENSEN */
#define WM8961_MBSEL 0x0001
/* MBSEL */
#define WM8961_MBSEL_MASK 0x0001
/* MBSEL */
#define WM8961_MBSEL_SHIFT 0
/* MBSEL */
#define WM8961_MBSEL_WIDTH 1
/* MBSEL */
/*
* R49 (0x31) - Class D Control 1
*/
#define WM8961_SPKR_ENA 0x0080
/* SPKR_ENA */
#define WM8961_SPKR_ENA_MASK 0x0080
/* SPKR_ENA */
#define WM8961_SPKR_ENA_SHIFT 7
/* SPKR_ENA */
#define WM8961_SPKR_ENA_WIDTH 1
/* SPKR_ENA */
#define WM8961_SPKL_ENA 0x0040
/* SPKL_ENA */
#define WM8961_SPKL_ENA_MASK 0x0040
/* SPKL_ENA */
#define WM8961_SPKL_ENA_SHIFT 6
/* SPKL_ENA */
#define WM8961_SPKL_ENA_WIDTH 1
/* SPKL_ENA */
/*
* R51 (0x33) - Class D Control 2
*/
#define WM8961_CLASSD_ACGAIN_MASK 0x0007
/* CLASSD_ACGAIN - [2:0] */
#define WM8961_CLASSD_ACGAIN_SHIFT 0
/* CLASSD_ACGAIN - [2:0] */
#define WM8961_CLASSD_ACGAIN_WIDTH 3
/* CLASSD_ACGAIN - [2:0] */
/*
* R56 (0x38) - Clocking 4
*/
#define WM8961_CLK_DCS_DIV_MASK 0x01E0
/* CLK_DCS_DIV - [8:5] */
#define WM8961_CLK_DCS_DIV_SHIFT 5
/* CLK_DCS_DIV - [8:5] */
#define WM8961_CLK_DCS_DIV_WIDTH 4
/* CLK_DCS_DIV - [8:5] */
#define WM8961_CLK_SYS_RATE_MASK 0x001E
/* CLK_SYS_RATE - [4:1] */
#define WM8961_CLK_SYS_RATE_SHIFT 1
/* CLK_SYS_RATE - [4:1] */
#define WM8961_CLK_SYS_RATE_WIDTH 4
/* CLK_SYS_RATE - [4:1] */
/*
* R57 (0x39) - DSP Sidetone 0
*/
#define WM8961_ADCR_DAC_SVOL_MASK 0x00F0
/* ADCR_DAC_SVOL - [7:4] */
#define WM8961_ADCR_DAC_SVOL_SHIFT 4
/* ADCR_DAC_SVOL - [7:4] */
#define WM8961_ADCR_DAC_SVOL_WIDTH 4
/* ADCR_DAC_SVOL - [7:4] */
#define WM8961_ADC_TO_DACR_MASK 0x000C
/* ADC_TO_DACR - [3:2] */
#define WM8961_ADC_TO_DACR_SHIFT 2
/* ADC_TO_DACR - [3:2] */
#define WM8961_ADC_TO_DACR_WIDTH 2
/* ADC_TO_DACR - [3:2] */
/*
* R58 (0x3A) - DSP Sidetone 1
*/
#define WM8961_ADCL_DAC_SVOL_MASK 0x00F0
/* ADCL_DAC_SVOL - [7:4] */
#define WM8961_ADCL_DAC_SVOL_SHIFT 4
/* ADCL_DAC_SVOL - [7:4] */
#define WM8961_ADCL_DAC_SVOL_WIDTH 4
/* ADCL_DAC_SVOL - [7:4] */
#define WM8961_ADC_TO_DACL_MASK 0x000C
/* ADC_TO_DACL - [3:2] */
#define WM8961_ADC_TO_DACL_SHIFT 2
/* ADC_TO_DACL - [3:2] */
#define WM8961_ADC_TO_DACL_WIDTH 2
/* ADC_TO_DACL - [3:2] */
/*
* R60 (0x3C) - DC Servo 0
*/
#define WM8961_DCS_ENA_CHAN_INL 0x0080
/* DCS_ENA_CHAN_INL */
#define WM8961_DCS_ENA_CHAN_INL_MASK 0x0080
/* DCS_ENA_CHAN_INL */
#define WM8961_DCS_ENA_CHAN_INL_SHIFT 7
/* DCS_ENA_CHAN_INL */
#define WM8961_DCS_ENA_CHAN_INL_WIDTH 1
/* DCS_ENA_CHAN_INL */
#define WM8961_DCS_TRIG_STARTUP_INL 0x0040
/* DCS_TRIG_STARTUP_INL */
#define WM8961_DCS_TRIG_STARTUP_INL_MASK 0x0040
/* DCS_TRIG_STARTUP_INL */
#define WM8961_DCS_TRIG_STARTUP_INL_SHIFT 6
/* DCS_TRIG_STARTUP_INL */
#define WM8961_DCS_TRIG_STARTUP_INL_WIDTH 1
/* DCS_TRIG_STARTUP_INL */
#define WM8961_DCS_TRIG_SERIES_INL 0x0010
/* DCS_TRIG_SERIES_INL */
#define WM8961_DCS_TRIG_SERIES_INL_MASK 0x0010
/* DCS_TRIG_SERIES_INL */
#define WM8961_DCS_TRIG_SERIES_INL_SHIFT 4
/* DCS_TRIG_SERIES_INL */
#define WM8961_DCS_TRIG_SERIES_INL_WIDTH 1
/* DCS_TRIG_SERIES_INL */
#define WM8961_DCS_ENA_CHAN_INR 0x0008
/* DCS_ENA_CHAN_INR */
#define WM8961_DCS_ENA_CHAN_INR_MASK 0x0008
/* DCS_ENA_CHAN_INR */
#define WM8961_DCS_ENA_CHAN_INR_SHIFT 3
/* DCS_ENA_CHAN_INR */
#define WM8961_DCS_ENA_CHAN_INR_WIDTH 1
/* DCS_ENA_CHAN_INR */
#define WM8961_DCS_TRIG_STARTUP_INR 0x0004
/* DCS_TRIG_STARTUP_INR */
#define WM8961_DCS_TRIG_STARTUP_INR_MASK 0x0004
/* DCS_TRIG_STARTUP_INR */
#define WM8961_DCS_TRIG_STARTUP_INR_SHIFT 2
/* DCS_TRIG_STARTUP_INR */
#define WM8961_DCS_TRIG_STARTUP_INR_WIDTH 1
/* DCS_TRIG_STARTUP_INR */
#define WM8961_DCS_TRIG_SERIES_INR 0x0001
/* DCS_TRIG_SERIES_INR */
#define WM8961_DCS_TRIG_SERIES_INR_MASK 0x0001
/* DCS_TRIG_SERIES_INR */
#define WM8961_DCS_TRIG_SERIES_INR_SHIFT 0
/* DCS_TRIG_SERIES_INR */
#define WM8961_DCS_TRIG_SERIES_INR_WIDTH 1
/* DCS_TRIG_SERIES_INR */
/*
* R61 (0x3D) - DC Servo 1
*/
#define WM8961_DCS_ENA_CHAN_HPL 0x0080
/* DCS_ENA_CHAN_HPL */
#define WM8961_DCS_ENA_CHAN_HPL_MASK 0x0080
/* DCS_ENA_CHAN_HPL */
#define WM8961_DCS_ENA_CHAN_HPL_SHIFT 7
/* DCS_ENA_CHAN_HPL */
#define WM8961_DCS_ENA_CHAN_HPL_WIDTH 1
/* DCS_ENA_CHAN_HPL */
#define WM8961_DCS_TRIG_STARTUP_HPL 0x0040
/* DCS_TRIG_STARTUP_HPL */
#define WM8961_DCS_TRIG_STARTUP_HPL_MASK 0x0040
/* DCS_TRIG_STARTUP_HPL */
#define WM8961_DCS_TRIG_STARTUP_HPL_SHIFT 6
/* DCS_TRIG_STARTUP_HPL */
#define WM8961_DCS_TRIG_STARTUP_HPL_WIDTH 1
/* DCS_TRIG_STARTUP_HPL */
#define WM8961_DCS_TRIG_SERIES_HPL 0x0010
/* DCS_TRIG_SERIES_HPL */
#define WM8961_DCS_TRIG_SERIES_HPL_MASK 0x0010
/* DCS_TRIG_SERIES_HPL */
#define WM8961_DCS_TRIG_SERIES_HPL_SHIFT 4
/* DCS_TRIG_SERIES_HPL */
#define WM8961_DCS_TRIG_SERIES_HPL_WIDTH 1
/* DCS_TRIG_SERIES_HPL */
#define WM8961_DCS_ENA_CHAN_HPR 0x0008
/* DCS_ENA_CHAN_HPR */
#define WM8961_DCS_ENA_CHAN_HPR_MASK 0x0008
/* DCS_ENA_CHAN_HPR */
#define WM8961_DCS_ENA_CHAN_HPR_SHIFT 3
/* DCS_ENA_CHAN_HPR */
#define WM8961_DCS_ENA_CHAN_HPR_WIDTH 1
/* DCS_ENA_CHAN_HPR */
#define WM8961_DCS_TRIG_STARTUP_HPR 0x0004
/* DCS_TRIG_STARTUP_HPR */
#define WM8961_DCS_TRIG_STARTUP_HPR_MASK 0x0004
/* DCS_TRIG_STARTUP_HPR */
#define WM8961_DCS_TRIG_STARTUP_HPR_SHIFT 2
/* DCS_TRIG_STARTUP_HPR */
#define WM8961_DCS_TRIG_STARTUP_HPR_WIDTH 1
/* DCS_TRIG_STARTUP_HPR */
#define WM8961_DCS_TRIG_SERIES_HPR 0x0001
/* DCS_TRIG_SERIES_HPR */
#define WM8961_DCS_TRIG_SERIES_HPR_MASK 0x0001
/* DCS_TRIG_SERIES_HPR */
#define WM8961_DCS_TRIG_SERIES_HPR_SHIFT 0
/* DCS_TRIG_SERIES_HPR */
#define WM8961_DCS_TRIG_SERIES_HPR_WIDTH 1
/* DCS_TRIG_SERIES_HPR */
/*
* R63 (0x3F) - DC Servo 3
*/
#define WM8961_DCS_FILT_BW_SERIES_MASK 0x0030
/* DCS_FILT_BW_SERIES - [5:4] */
#define WM8961_DCS_FILT_BW_SERIES_SHIFT 4
/* DCS_FILT_BW_SERIES - [5:4] */
#define WM8961_DCS_FILT_BW_SERIES_WIDTH 2
/* DCS_FILT_BW_SERIES - [5:4] */
/*
* R65 (0x41) - DC Servo 5
*/
#define WM8961_DCS_SERIES_NO_HP_MASK 0x007F
/* DCS_SERIES_NO_HP - [6:0] */
#define WM8961_DCS_SERIES_NO_HP_SHIFT 0
/* DCS_SERIES_NO_HP - [6:0] */
#define WM8961_DCS_SERIES_NO_HP_WIDTH 7
/* DCS_SERIES_NO_HP - [6:0] */
/*
* R68 (0x44) - Analogue PGA Bias
*/
#define WM8961_HP_PGAS_BIAS_MASK 0x0007
/* HP_PGAS_BIAS - [2:0] */
#define WM8961_HP_PGAS_BIAS_SHIFT 0
/* HP_PGAS_BIAS - [2:0] */
#define WM8961_HP_PGAS_BIAS_WIDTH 3
/* HP_PGAS_BIAS - [2:0] */
/*
* R69 (0x45) - Analogue HP 0
*/
#define WM8961_HPL_RMV_SHORT 0x0080
/* HPL_RMV_SHORT */
#define WM8961_HPL_RMV_SHORT_MASK 0x0080
/* HPL_RMV_SHORT */
#define WM8961_HPL_RMV_SHORT_SHIFT 7
/* HPL_RMV_SHORT */
#define WM8961_HPL_RMV_SHORT_WIDTH 1
/* HPL_RMV_SHORT */
#define WM8961_HPL_ENA_OUTP 0x0040
/* HPL_ENA_OUTP */
#define WM8961_HPL_ENA_OUTP_MASK 0x0040
/* HPL_ENA_OUTP */
#define WM8961_HPL_ENA_OUTP_SHIFT 6
/* HPL_ENA_OUTP */
#define WM8961_HPL_ENA_OUTP_WIDTH 1
/* HPL_ENA_OUTP */
#define WM8961_HPL_ENA_DLY 0x0020
/* HPL_ENA_DLY */
#define WM8961_HPL_ENA_DLY_MASK 0x0020
/* HPL_ENA_DLY */
#define WM8961_HPL_ENA_DLY_SHIFT 5
/* HPL_ENA_DLY */
#define WM8961_HPL_ENA_DLY_WIDTH 1
/* HPL_ENA_DLY */
#define WM8961_HPL_ENA 0x0010
/* HPL_ENA */
#define WM8961_HPL_ENA_MASK 0x0010
/* HPL_ENA */
#define WM8961_HPL_ENA_SHIFT 4
/* HPL_ENA */
#define WM8961_HPL_ENA_WIDTH 1
/* HPL_ENA */
#define WM8961_HPR_RMV_SHORT 0x0008
/* HPR_RMV_SHORT */
#define WM8961_HPR_RMV_SHORT_MASK 0x0008
/* HPR_RMV_SHORT */
#define WM8961_HPR_RMV_SHORT_SHIFT 3
/* HPR_RMV_SHORT */
#define WM8961_HPR_RMV_SHORT_WIDTH 1
/* HPR_RMV_SHORT */
#define WM8961_HPR_ENA_OUTP 0x0004
/* HPR_ENA_OUTP */
#define WM8961_HPR_ENA_OUTP_MASK 0x0004
/* HPR_ENA_OUTP */
#define WM8961_HPR_ENA_OUTP_SHIFT 2
/* HPR_ENA_OUTP */
#define WM8961_HPR_ENA_OUTP_WIDTH 1
/* HPR_ENA_OUTP */
#define WM8961_HPR_ENA_DLY 0x0002
/* HPR_ENA_DLY */
#define WM8961_HPR_ENA_DLY_MASK 0x0002
/* HPR_ENA_DLY */
#define WM8961_HPR_ENA_DLY_SHIFT 1
/* HPR_ENA_DLY */
#define WM8961_HPR_ENA_DLY_WIDTH 1
/* HPR_ENA_DLY */
#define WM8961_HPR_ENA 0x0001
/* HPR_ENA */
#define WM8961_HPR_ENA_MASK 0x0001
/* HPR_ENA */
#define WM8961_HPR_ENA_SHIFT 0
/* HPR_ENA */
#define WM8961_HPR_ENA_WIDTH 1
/* HPR_ENA */
/*
* R71 (0x47) - Analogue HP 2
*/
#define WM8961_HPL_VOL_MASK 0x01C0
/* HPL_VOL - [8:6] */
#define WM8961_HPL_VOL_SHIFT 6
/* HPL_VOL - [8:6] */
#define WM8961_HPL_VOL_WIDTH 3
/* HPL_VOL - [8:6] */
#define WM8961_HPR_VOL_MASK 0x0038
/* HPR_VOL - [5:3] */
#define WM8961_HPR_VOL_SHIFT 3
/* HPR_VOL - [5:3] */
#define WM8961_HPR_VOL_WIDTH 3
/* HPR_VOL - [5:3] */
#define WM8961_HP_BIAS_BOOST_MASK 0x0007
/* HP_BIAS_BOOST - [2:0] */
#define WM8961_HP_BIAS_BOOST_SHIFT 0
/* HP_BIAS_BOOST - [2:0] */
#define WM8961_HP_BIAS_BOOST_WIDTH 3
/* HP_BIAS_BOOST - [2:0] */
/*
* R72 (0x48) - Charge Pump 1
*/
#define WM8961_CP_ENA 0x0001
/* CP_ENA */
#define WM8961_CP_ENA_MASK 0x0001
/* CP_ENA */
#define WM8961_CP_ENA_SHIFT 0
/* CP_ENA */
#define WM8961_CP_ENA_WIDTH 1
/* CP_ENA */
/*
* R82 (0x52) - Charge Pump B
*/
#define WM8961_CP_DYN_PWR_MASK 0x0003
/* CP_DYN_PWR - [1:0] */
#define WM8961_CP_DYN_PWR_SHIFT 0
/* CP_DYN_PWR - [1:0] */
#define WM8961_CP_DYN_PWR_WIDTH 2
/* CP_DYN_PWR - [1:0] */
/*
* R87 (0x57) - Write Sequencer 1
*/
#define WM8961_WSEQ_ENA 0x0020
/* WSEQ_ENA */
#define WM8961_WSEQ_ENA_MASK 0x0020
/* WSEQ_ENA */
#define WM8961_WSEQ_ENA_SHIFT 5
/* WSEQ_ENA */
#define WM8961_WSEQ_ENA_WIDTH 1
/* WSEQ_ENA */
#define WM8961_WSEQ_WRITE_INDEX_MASK 0x001F
/* WSEQ_WRITE_INDEX - [4:0] */
#define WM8961_WSEQ_WRITE_INDEX_SHIFT 0
/* WSEQ_WRITE_INDEX - [4:0] */
#define WM8961_WSEQ_WRITE_INDEX_WIDTH 5
/* WSEQ_WRITE_INDEX - [4:0] */
/*
* R88 (0x58) - Write Sequencer 2
*/
#define WM8961_WSEQ_EOS 0x0100
/* WSEQ_EOS */
#define WM8961_WSEQ_EOS_MASK 0x0100
/* WSEQ_EOS */
#define WM8961_WSEQ_EOS_SHIFT 8
/* WSEQ_EOS */
#define WM8961_WSEQ_EOS_WIDTH 1
/* WSEQ_EOS */
#define WM8961_WSEQ_ADDR_MASK 0x00FF
/* WSEQ_ADDR - [7:0] */
#define WM8961_WSEQ_ADDR_SHIFT 0
/* WSEQ_ADDR - [7:0] */
#define WM8961_WSEQ_ADDR_WIDTH 8
/* WSEQ_ADDR - [7:0] */
/*
* R89 (0x59) - Write Sequencer 3
*/
#define WM8961_WSEQ_DATA_MASK 0x00FF
/* WSEQ_DATA - [7:0] */
#define WM8961_WSEQ_DATA_SHIFT 0
/* WSEQ_DATA - [7:0] */
#define WM8961_WSEQ_DATA_WIDTH 8
/* WSEQ_DATA - [7:0] */
/*
* R90 (0x5A) - Write Sequencer 4
*/
#define WM8961_WSEQ_ABORT 0x0100
/* WSEQ_ABORT */
#define WM8961_WSEQ_ABORT_MASK 0x0100
/* WSEQ_ABORT */
#define WM8961_WSEQ_ABORT_SHIFT 8
/* WSEQ_ABORT */
#define WM8961_WSEQ_ABORT_WIDTH 1
/* WSEQ_ABORT */
#define WM8961_WSEQ_START 0x0080
/* WSEQ_START */
#define WM8961_WSEQ_START_MASK 0x0080
/* WSEQ_START */
#define WM8961_WSEQ_START_SHIFT 7
/* WSEQ_START */
#define WM8961_WSEQ_START_WIDTH 1
/* WSEQ_START */
#define WM8961_WSEQ_START_INDEX_MASK 0x003F
/* WSEQ_START_INDEX - [5:0] */
#define WM8961_WSEQ_START_INDEX_SHIFT 0
/* WSEQ_START_INDEX - [5:0] */
#define WM8961_WSEQ_START_INDEX_WIDTH 6
/* WSEQ_START_INDEX - [5:0] */
/*
* R91 (0x5B) - Write Sequencer 5
*/
#define WM8961_WSEQ_DATA_WIDTH_MASK 0x0070
/* WSEQ_DATA_WIDTH - [6:4] */
#define WM8961_WSEQ_DATA_WIDTH_SHIFT 4
/* WSEQ_DATA_WIDTH - [6:4] */
#define WM8961_WSEQ_DATA_WIDTH_WIDTH 3
/* WSEQ_DATA_WIDTH - [6:4] */
#define WM8961_WSEQ_DATA_START_MASK 0x000F
/* WSEQ_DATA_START - [3:0] */
#define WM8961_WSEQ_DATA_START_SHIFT 0
/* WSEQ_DATA_START - [3:0] */
#define WM8961_WSEQ_DATA_START_WIDTH 4
/* WSEQ_DATA_START - [3:0] */
/*
* R92 (0x5C) - Write Sequencer 6
*/
#define WM8961_WSEQ_DELAY_MASK 0x000F
/* WSEQ_DELAY - [3:0] */
#define WM8961_WSEQ_DELAY_SHIFT 0
/* WSEQ_DELAY - [3:0] */
#define WM8961_WSEQ_DELAY_WIDTH 4
/* WSEQ_DELAY - [3:0] */
/*
* R93 (0x5D) - Write Sequencer 7
*/
#define WM8961_WSEQ_BUSY 0x0001
/* WSEQ_BUSY */
#define WM8961_WSEQ_BUSY_MASK 0x0001
/* WSEQ_BUSY */
#define WM8961_WSEQ_BUSY_SHIFT 0
/* WSEQ_BUSY */
#define WM8961_WSEQ_BUSY_WIDTH 1
/* WSEQ_BUSY */
/*
* R252 (0xFC) - General test 1
*/
#define WM8961_ARA_ENA 0x0002
/* ARA_ENA */
#define WM8961_ARA_ENA_MASK 0x0002
/* ARA_ENA */
#define WM8961_ARA_ENA_SHIFT 1
/* ARA_ENA */
#define WM8961_ARA_ENA_WIDTH 1
/* ARA_ENA */
#define WM8961_AUTO_INC 0x0001
/* AUTO_INC */
#define WM8961_AUTO_INC_MASK 0x0001
/* AUTO_INC */
#define WM8961_AUTO_INC_SHIFT 0
/* AUTO_INC */
#define WM8961_AUTO_INC_WIDTH 1
/* AUTO_INC */
#endif
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