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
06cddefc
Commit
06cddefc
authored
Aug 07, 2009
by
Mark Brown
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'reg-cache' into for-2.6.32
parents
b9b5cc26
27ded041
Changes
19
Hide whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
1114 additions
and
1785 deletions
+1114
-1785
include/sound/soc.h
include/sound/soc.h
+10
-1
sound/soc/Makefile
sound/soc/Makefile
+1
-1
sound/soc/codecs/tlv320aic3x.c
sound/soc/codecs/tlv320aic3x.c
+2
-9
sound/soc/codecs/wm8510.c
sound/soc/codecs/wm8510.c
+53
-121
sound/soc/codecs/wm8523.c
sound/soc/codecs/wm8523.c
+21
-77
sound/soc/codecs/wm8580.c
sound/soc/codecs/wm8580.c
+44
-110
sound/soc/codecs/wm8728.c
sound/soc/codecs/wm8728.c
+26
-85
sound/soc/codecs/wm8731.c
sound/soc/codecs/wm8731.c
+33
-108
sound/soc/codecs/wm8750.c
sound/soc/codecs/wm8750.c
+47
-107
sound/soc/codecs/wm8900.c
sound/soc/codecs/wm8900.c
+116
-203
sound/soc/codecs/wm8903.c
sound/soc/codecs/wm8903.c
+86
-158
sound/soc/codecs/wm8940.c
sound/soc/codecs/wm8940.c
+52
-91
sound/soc/codecs/wm8960.c
sound/soc/codecs/wm8960.c
+75
-125
sound/soc/codecs/wm8961.c
sound/soc/codecs/wm8961.c
+85
-146
sound/soc/codecs/wm8971.c
sound/soc/codecs/wm8971.c
+47
-80
sound/soc/codecs/wm8988.c
sound/soc/codecs/wm8988.c
+37
-101
sound/soc/codecs/wm8990.c
sound/soc/codecs/wm8990.c
+76
-118
sound/soc/codecs/wm9081.c
sound/soc/codecs/wm9081.c
+85
-144
sound/soc/soc-cache.c
sound/soc/soc-cache.c
+218
-0
No files found.
include/sound/soc.h
View file @
06cddefc
...
...
@@ -209,11 +209,20 @@ typedef int (*hw_read_t)(void *,char* ,int);
extern
struct
snd_ac97_bus_ops
soc_ac97_ops
;
enum
snd_soc_control_type
{
SND_SOC_CUSTOM
,
SND_SOC_I2C
,
SND_SOC_SPI
,
};
int
snd_soc_register_platform
(
struct
snd_soc_platform
*
platform
);
void
snd_soc_unregister_platform
(
struct
snd_soc_platform
*
platform
);
int
snd_soc_register_codec
(
struct
snd_soc_codec
*
codec
);
void
snd_soc_unregister_codec
(
struct
snd_soc_codec
*
codec
);
int
snd_soc_codec_volatile_register
(
struct
snd_soc_codec
*
codec
,
int
reg
);
int
snd_soc_codec_set_cache_io
(
struct
snd_soc_codec
*
codec
,
int
addr_bits
,
int
data_bits
,
enum
snd_soc_control_type
control
);
#ifdef CONFIG_PM
int
snd_soc_suspend_device
(
struct
device
*
dev
);
...
...
@@ -387,7 +396,7 @@ struct snd_soc_codec {
int
(
*
volatile_register
)(
unsigned
int
);
int
(
*
readable_register
)(
unsigned
int
);
hw_write_t
hw_write
;
hw_read_t
hw_read
;
unsigned
int
(
*
hw_read
)(
struct
snd_soc_codec
*
,
unsigned
int
)
;
void
*
reg_cache
;
short
reg_cache_size
;
short
reg_cache_step
;
...
...
sound/soc/Makefile
View file @
06cddefc
snd-soc-core-objs
:=
soc-core.o soc-dapm.o soc-jack.o
snd-soc-core-objs
:=
soc-core.o soc-dapm.o soc-jack.o
soc-cache.o
obj-$(CONFIG_SND_SOC)
+=
snd-soc-core.o
obj-$(CONFIG_SND_SOC)
+=
codecs/
...
...
sound/soc/codecs/tlv320aic3x.c
View file @
06cddefc
...
...
@@ -145,8 +145,8 @@ static int aic3x_read(struct snd_soc_codec *codec, unsigned int reg,
u8
*
value
)
{
*
value
=
reg
&
0xff
;
if
(
codec
->
hw_read
(
codec
->
control_data
,
value
,
1
)
!=
1
)
return
-
EIO
;
value
[
0
]
=
i2c_smbus_read_byte_data
(
codec
->
control_data
,
value
[
0
])
;
aic3x_write_reg_cache
(
codec
,
reg
,
*
value
);
return
0
;
...
...
@@ -1325,12 +1325,6 @@ static struct i2c_driver aic3x_i2c_driver = {
.
id_table
=
aic3x_i2c_id
,
};
static
int
aic3x_i2c_read
(
struct
i2c_client
*
client
,
u8
*
value
,
int
len
)
{
value
[
0
]
=
i2c_smbus_read_byte_data
(
client
,
value
[
0
]);
return
(
len
==
1
);
}
static
int
aic3x_add_i2c_device
(
struct
platform_device
*
pdev
,
const
struct
aic3x_setup_data
*
setup
)
{
...
...
@@ -1403,7 +1397,6 @@ static int aic3x_probe(struct platform_device *pdev)
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
if
(
setup
->
i2c_address
)
{
codec
->
hw_write
=
(
hw_write_t
)
i2c_master_send
;
codec
->
hw_read
=
(
hw_read_t
)
aic3x_i2c_read
;
ret
=
aic3x_add_i2c_device
(
pdev
,
setup
);
}
#else
...
...
sound/soc/codecs/wm8510.c
View file @
06cddefc
...
...
@@ -58,55 +58,7 @@ static const u16 wm8510_reg[WM8510_CACHEREGNUM] = {
#define WM8510_POWER1_BIASEN 0x08
#define WM8510_POWER1_BUFIOEN 0x10
/*
* read wm8510 register cache
*/
static
inline
unsigned
int
wm8510_read_reg_cache
(
struct
snd_soc_codec
*
codec
,
unsigned
int
reg
)
{
u16
*
cache
=
codec
->
reg_cache
;
if
(
reg
==
WM8510_RESET
)
return
0
;
if
(
reg
>=
WM8510_CACHEREGNUM
)
return
-
1
;
return
cache
[
reg
];
}
/*
* write wm8510 register cache
*/
static
inline
void
wm8510_write_reg_cache
(
struct
snd_soc_codec
*
codec
,
u16
reg
,
unsigned
int
value
)
{
u16
*
cache
=
codec
->
reg_cache
;
if
(
reg
>=
WM8510_CACHEREGNUM
)
return
;
cache
[
reg
]
=
value
;
}
/*
* write to the WM8510 register space
*/
static
int
wm8510_write
(
struct
snd_soc_codec
*
codec
,
unsigned
int
reg
,
unsigned
int
value
)
{
u8
data
[
2
];
/* data is
* D15..D9 WM8510 register offset
* D8...D0 register data
*/
data
[
0
]
=
(
reg
<<
1
)
|
((
value
>>
8
)
&
0x0001
);
data
[
1
]
=
value
&
0x00ff
;
wm8510_write_reg_cache
(
codec
,
reg
,
value
);
if
(
codec
->
hw_write
(
codec
->
control_data
,
data
,
2
)
==
2
)
return
0
;
else
return
-
EIO
;
}
#define wm8510_reset(c) wm8510_write(c, WM8510_RESET, 0)
#define wm8510_reset(c) snd_soc_write(c, WM8510_RESET, 0)
static
const
char
*
wm8510_companding
[]
=
{
"Off"
,
"NC"
,
"u-law"
,
"A-law"
};
static
const
char
*
wm8510_deemp
[]
=
{
"None"
,
"32kHz"
,
"44.1kHz"
,
"48kHz"
};
...
...
@@ -327,27 +279,27 @@ static int wm8510_set_dai_pll(struct snd_soc_dai *codec_dai,
if
(
freq_in
==
0
||
freq_out
==
0
)
{
/* Clock CODEC directly from MCLK */
reg
=
wm8510_read_reg_cache
(
codec
,
WM8510_CLOCK
);
wm8510
_write
(
codec
,
WM8510_CLOCK
,
reg
&
0x0ff
);
reg
=
snd_soc_read
(
codec
,
WM8510_CLOCK
);
snd_soc
_write
(
codec
,
WM8510_CLOCK
,
reg
&
0x0ff
);
/* Turn off PLL */
reg
=
wm8510_read_reg_cache
(
codec
,
WM8510_POWER1
);
wm8510
_write
(
codec
,
WM8510_POWER1
,
reg
&
0x1df
);
reg
=
snd_soc_read
(
codec
,
WM8510_POWER1
);
snd_soc
_write
(
codec
,
WM8510_POWER1
,
reg
&
0x1df
);
return
0
;
}
pll_factors
(
freq_out
*
4
,
freq_in
);
wm8510
_write
(
codec
,
WM8510_PLLN
,
(
pll_div
.
pre_div
<<
4
)
|
pll_div
.
n
);
wm8510
_write
(
codec
,
WM8510_PLLK1
,
pll_div
.
k
>>
18
);
wm8510
_write
(
codec
,
WM8510_PLLK2
,
(
pll_div
.
k
>>
9
)
&
0x1ff
);
wm8510
_write
(
codec
,
WM8510_PLLK3
,
pll_div
.
k
&
0x1ff
);
reg
=
wm8510_read_reg_cache
(
codec
,
WM8510_POWER1
);
wm8510
_write
(
codec
,
WM8510_POWER1
,
reg
|
0x020
);
snd_soc
_write
(
codec
,
WM8510_PLLN
,
(
pll_div
.
pre_div
<<
4
)
|
pll_div
.
n
);
snd_soc
_write
(
codec
,
WM8510_PLLK1
,
pll_div
.
k
>>
18
);
snd_soc
_write
(
codec
,
WM8510_PLLK2
,
(
pll_div
.
k
>>
9
)
&
0x1ff
);
snd_soc
_write
(
codec
,
WM8510_PLLK3
,
pll_div
.
k
&
0x1ff
);
reg
=
snd_soc_read
(
codec
,
WM8510_POWER1
);
snd_soc
_write
(
codec
,
WM8510_POWER1
,
reg
|
0x020
);
/* Run CODEC from PLL instead of MCLK */
reg
=
wm8510_read_reg_cache
(
codec
,
WM8510_CLOCK
);
wm8510
_write
(
codec
,
WM8510_CLOCK
,
reg
|
0x100
);
reg
=
snd_soc_read
(
codec
,
WM8510_CLOCK
);
snd_soc
_write
(
codec
,
WM8510_CLOCK
,
reg
|
0x100
);
return
0
;
}
...
...
@@ -363,24 +315,24 @@ static int wm8510_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
switch
(
div_id
)
{
case
WM8510_OPCLKDIV
:
reg
=
wm8510_read_reg_cache
(
codec
,
WM8510_GPIO
)
&
0x1cf
;
wm8510
_write
(
codec
,
WM8510_GPIO
,
reg
|
div
);
reg
=
snd_soc_read
(
codec
,
WM8510_GPIO
)
&
0x1cf
;
snd_soc
_write
(
codec
,
WM8510_GPIO
,
reg
|
div
);
break
;
case
WM8510_MCLKDIV
:
reg
=
wm8510_read_reg_cache
(
codec
,
WM8510_CLOCK
)
&
0x11f
;
wm8510
_write
(
codec
,
WM8510_CLOCK
,
reg
|
div
);
reg
=
snd_soc_read
(
codec
,
WM8510_CLOCK
)
&
0x11f
;
snd_soc
_write
(
codec
,
WM8510_CLOCK
,
reg
|
div
);
break
;
case
WM8510_ADCCLK
:
reg
=
wm8510_read_reg_cache
(
codec
,
WM8510_ADC
)
&
0x1f7
;
wm8510
_write
(
codec
,
WM8510_ADC
,
reg
|
div
);
reg
=
snd_soc_read
(
codec
,
WM8510_ADC
)
&
0x1f7
;
snd_soc
_write
(
codec
,
WM8510_ADC
,
reg
|
div
);
break
;
case
WM8510_DACCLK
:
reg
=
wm8510_read_reg_cache
(
codec
,
WM8510_DAC
)
&
0x1f7
;
wm8510
_write
(
codec
,
WM8510_DAC
,
reg
|
div
);
reg
=
snd_soc_read
(
codec
,
WM8510_DAC
)
&
0x1f7
;
snd_soc
_write
(
codec
,
WM8510_DAC
,
reg
|
div
);
break
;
case
WM8510_BCLKDIV
:
reg
=
wm8510_read_reg_cache
(
codec
,
WM8510_CLOCK
)
&
0x1e3
;
wm8510
_write
(
codec
,
WM8510_CLOCK
,
reg
|
div
);
reg
=
snd_soc_read
(
codec
,
WM8510_CLOCK
)
&
0x1e3
;
snd_soc
_write
(
codec
,
WM8510_CLOCK
,
reg
|
div
);
break
;
default:
return
-
EINVAL
;
...
...
@@ -394,7 +346,7 @@ static int wm8510_set_dai_fmt(struct snd_soc_dai *codec_dai,
{
struct
snd_soc_codec
*
codec
=
codec_dai
->
codec
;
u16
iface
=
0
;
u16
clk
=
wm8510_read_reg_cache
(
codec
,
WM8510_CLOCK
)
&
0x1fe
;
u16
clk
=
snd_soc_read
(
codec
,
WM8510_CLOCK
)
&
0x1fe
;
/* set master/slave audio interface */
switch
(
fmt
&
SND_SOC_DAIFMT_MASTER_MASK
)
{
...
...
@@ -441,8 +393,8 @@ static int wm8510_set_dai_fmt(struct snd_soc_dai *codec_dai,
return
-
EINVAL
;
}
wm8510
_write
(
codec
,
WM8510_IFACE
,
iface
);
wm8510
_write
(
codec
,
WM8510_CLOCK
,
clk
);
snd_soc
_write
(
codec
,
WM8510_IFACE
,
iface
);
snd_soc
_write
(
codec
,
WM8510_CLOCK
,
clk
);
return
0
;
}
...
...
@@ -453,8 +405,8 @@ static int wm8510_pcm_hw_params(struct snd_pcm_substream *substream,
struct
snd_soc_pcm_runtime
*
rtd
=
substream
->
private_data
;
struct
snd_soc_device
*
socdev
=
rtd
->
socdev
;
struct
snd_soc_codec
*
codec
=
socdev
->
card
->
codec
;
u16
iface
=
wm8510_read_reg_cache
(
codec
,
WM8510_IFACE
)
&
0x19f
;
u16
adn
=
wm8510_read_reg_cache
(
codec
,
WM8510_ADD
)
&
0x1f1
;
u16
iface
=
snd_soc_read
(
codec
,
WM8510_IFACE
)
&
0x19f
;
u16
adn
=
snd_soc_read
(
codec
,
WM8510_ADD
)
&
0x1f1
;
/* bit size */
switch
(
params_format
(
params
))
{
...
...
@@ -493,20 +445,20 @@ static int wm8510_pcm_hw_params(struct snd_pcm_substream *substream,
break
;
}
wm8510
_write
(
codec
,
WM8510_IFACE
,
iface
);
wm8510
_write
(
codec
,
WM8510_ADD
,
adn
);
snd_soc
_write
(
codec
,
WM8510_IFACE
,
iface
);
snd_soc
_write
(
codec
,
WM8510_ADD
,
adn
);
return
0
;
}
static
int
wm8510_mute
(
struct
snd_soc_dai
*
dai
,
int
mute
)
{
struct
snd_soc_codec
*
codec
=
dai
->
codec
;
u16
mute_reg
=
wm8510_read_reg_cache
(
codec
,
WM8510_DAC
)
&
0xffbf
;
u16
mute_reg
=
snd_soc_read
(
codec
,
WM8510_DAC
)
&
0xffbf
;
if
(
mute
)
wm8510
_write
(
codec
,
WM8510_DAC
,
mute_reg
|
0x40
);
snd_soc
_write
(
codec
,
WM8510_DAC
,
mute_reg
|
0x40
);
else
wm8510
_write
(
codec
,
WM8510_DAC
,
mute_reg
);
snd_soc
_write
(
codec
,
WM8510_DAC
,
mute_reg
);
return
0
;
}
...
...
@@ -514,13 +466,13 @@ static int wm8510_mute(struct snd_soc_dai *dai, int mute)
static
int
wm8510_set_bias_level
(
struct
snd_soc_codec
*
codec
,
enum
snd_soc_bias_level
level
)
{
u16
power1
=
wm8510_read_reg_cache
(
codec
,
WM8510_POWER1
)
&
~
0x3
;
u16
power1
=
snd_soc_read
(
codec
,
WM8510_POWER1
)
&
~
0x3
;
switch
(
level
)
{
case
SND_SOC_BIAS_ON
:
case
SND_SOC_BIAS_PREPARE
:
power1
|=
0x1
;
/* VMID 50k */
wm8510
_write
(
codec
,
WM8510_POWER1
,
power1
);
snd_soc
_write
(
codec
,
WM8510_POWER1
,
power1
);
break
;
case
SND_SOC_BIAS_STANDBY
:
...
...
@@ -528,18 +480,18 @@ static int wm8510_set_bias_level(struct snd_soc_codec *codec,
if
(
codec
->
bias_level
==
SND_SOC_BIAS_OFF
)
{
/* Initial cap charge at VMID 5k */
wm8510
_write
(
codec
,
WM8510_POWER1
,
power1
|
0x3
);
snd_soc
_write
(
codec
,
WM8510_POWER1
,
power1
|
0x3
);
mdelay
(
100
);
}
power1
|=
0x2
;
/* VMID 500k */
wm8510
_write
(
codec
,
WM8510_POWER1
,
power1
);
snd_soc
_write
(
codec
,
WM8510_POWER1
,
power1
);
break
;
case
SND_SOC_BIAS_OFF
:
wm8510
_write
(
codec
,
WM8510_POWER1
,
0
);
wm8510
_write
(
codec
,
WM8510_POWER2
,
0
);
wm8510
_write
(
codec
,
WM8510_POWER3
,
0
);
snd_soc
_write
(
codec
,
WM8510_POWER1
,
0
);
snd_soc
_write
(
codec
,
WM8510_POWER2
,
0
);
snd_soc
_write
(
codec
,
WM8510_POWER3
,
0
);
break
;
}
...
...
@@ -613,15 +565,14 @@ static int wm8510_resume(struct platform_device *pdev)
* initialise the WM8510 driver
* register the mixer and dsp interfaces with the kernel
*/
static
int
wm8510_init
(
struct
snd_soc_device
*
socdev
)
static
int
wm8510_init
(
struct
snd_soc_device
*
socdev
,
enum
snd_soc_control_type
control
)
{
struct
snd_soc_codec
*
codec
=
socdev
->
card
->
codec
;
int
ret
=
0
;
codec
->
name
=
"WM8510"
;
codec
->
owner
=
THIS_MODULE
;
codec
->
read
=
wm8510_read_reg_cache
;
codec
->
write
=
wm8510_write
;
codec
->
set_bias_level
=
wm8510_set_bias_level
;
codec
->
dai
=
&
wm8510_dai
;
codec
->
num_dai
=
1
;
...
...
@@ -631,13 +582,20 @@ static int wm8510_init(struct snd_soc_device *socdev)
if
(
codec
->
reg_cache
==
NULL
)
return
-
ENOMEM
;
ret
=
snd_soc_codec_set_cache_io
(
codec
,
7
,
9
,
control
);
if
(
ret
<
0
)
{
printk
(
KERN_ERR
"wm8510: failed to set cache I/O: %d
\n
"
,
ret
);
goto
err
;
}
wm8510_reset
(
codec
);
/* register pcms */
ret
=
snd_soc_new_pcms
(
socdev
,
SNDRV_DEFAULT_IDX1
,
SNDRV_DEFAULT_STR1
);
if
(
ret
<
0
)
{
printk
(
KERN_ERR
"wm8510: failed to create pcms
\n
"
);
goto
pcm_
err
;
goto
err
;
}
/* power on device */
...
...
@@ -656,7 +614,7 @@ static int wm8510_init(struct snd_soc_device *socdev)
card_err:
snd_soc_free_pcms
(
socdev
);
snd_soc_dapm_free
(
socdev
);
pcm_
err:
err:
kfree
(
codec
->
reg_cache
);
return
ret
;
}
...
...
@@ -679,7 +637,7 @@ static int wm8510_i2c_probe(struct i2c_client *i2c,
i2c_set_clientdata
(
i2c
,
codec
);
codec
->
control_data
=
i2c
;
ret
=
wm8510_init
(
socdev
);
ret
=
wm8510_init
(
socdev
,
SND_SOC_I2C
);
if
(
ret
<
0
)
pr_err
(
"failed to initialise WM8510
\n
"
);
...
...
@@ -759,7 +717,7 @@ static int __devinit wm8510_spi_probe(struct spi_device *spi)
codec
->
control_data
=
spi
;
ret
=
wm8510_init
(
socdev
);
ret
=
wm8510_init
(
socdev
,
SND_SOC_SPI
);
if
(
ret
<
0
)
dev_err
(
&
spi
->
dev
,
"failed to initialise WM8510
\n
"
);
...
...
@@ -780,30 +738,6 @@ static struct spi_driver wm8510_spi_driver = {
.
probe
=
wm8510_spi_probe
,
.
remove
=
__devexit_p
(
wm8510_spi_remove
),
};
static
int
wm8510_spi_write
(
struct
spi_device
*
spi
,
const
char
*
data
,
int
len
)
{
struct
spi_transfer
t
;
struct
spi_message
m
;
u8
msg
[
2
];
if
(
len
<=
0
)
return
0
;
msg
[
0
]
=
data
[
0
];
msg
[
1
]
=
data
[
1
];
spi_message_init
(
&
m
);
memset
(
&
t
,
0
,
(
sizeof
t
));
t
.
tx_buf
=
&
msg
[
0
];
t
.
len
=
len
;
spi_message_add_tail
(
&
t
,
&
m
);
spi_sync
(
spi
,
&
m
);
return
len
;
}
#endif
/* CONFIG_SPI_MASTER */
static
int
wm8510_probe
(
struct
platform_device
*
pdev
)
...
...
@@ -828,13 +762,11 @@ static int wm8510_probe(struct platform_device *pdev)
wm8510_socdev
=
socdev
;
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
if
(
setup
->
i2c_address
)
{
codec
->
hw_write
=
(
hw_write_t
)
i2c_master_send
;
ret
=
wm8510_add_i2c_device
(
pdev
,
setup
);
}
#endif
#if defined(CONFIG_SPI_MASTER)
if
(
setup
->
spi
)
{
codec
->
hw_write
=
(
hw_write_t
)
wm8510_spi_write
;
ret
=
spi_register_driver
(
&
wm8510_spi_driver
);
if
(
ret
!=
0
)
printk
(
KERN_ERR
"can't add spi driver"
);
...
...
sound/soc/codecs/wm8523.c
View file @
06cddefc
...
...
@@ -62,7 +62,7 @@ static const u16 wm8523_reg[WM8523_REGISTER_COUNT] = {
0x0000
,
/* R8 - ZERO_DETECT */
};
static
int
wm8523_volatile
(
unsigned
int
reg
)
static
int
wm8523_volatile
_register
(
unsigned
int
reg
)
{
switch
(
reg
)
{
case
WM8523_DEVICE_ID
:
...
...
@@ -73,71 +73,9 @@ static int wm8523_volatile(unsigned int reg)
}
}
static
int
wm8523_write
(
struct
snd_soc_codec
*
codec
,
unsigned
int
reg
,
unsigned
int
value
)
{
struct
wm8523_priv
*
wm8523
=
codec
->
private_data
;
u8
data
[
3
];
BUG_ON
(
reg
>
WM8523_MAX_REGISTER
);
data
[
0
]
=
reg
;
data
[
1
]
=
(
value
>>
8
)
&
0x00ff
;
data
[
2
]
=
value
&
0x00ff
;
if
(
!
wm8523_volatile
(
reg
))
wm8523
->
reg_cache
[
reg
]
=
value
;
if
(
codec
->
hw_write
(
codec
->
control_data
,
data
,
3
)
==
3
)
return
0
;
else
return
-
EIO
;
}
static
int
wm8523_reset
(
struct
snd_soc_codec
*
codec
)
{
return
wm8523_write
(
codec
,
WM8523_DEVICE_ID
,
0
);
}
static
unsigned
int
wm8523_read_hw
(
struct
snd_soc_codec
*
codec
,
u8
reg
)
{
struct
i2c_msg
xfer
[
2
];
u16
data
;
int
ret
;
struct
i2c_client
*
i2c
=
codec
->
control_data
;
/* Write register */
xfer
[
0
].
addr
=
i2c
->
addr
;
xfer
[
0
].
flags
=
0
;
xfer
[
0
].
len
=
1
;
xfer
[
0
].
buf
=
&
reg
;
/* Read data */
xfer
[
1
].
addr
=
i2c
->
addr
;
xfer
[
1
].
flags
=
I2C_M_RD
;
xfer
[
1
].
len
=
2
;
xfer
[
1
].
buf
=
(
u8
*
)
&
data
;
ret
=
i2c_transfer
(
i2c
->
adapter
,
xfer
,
2
);
if
(
ret
!=
2
)
{
dev_err
(
codec
->
dev
,
"Failed to read 0x%x: %d
\n
"
,
reg
,
ret
);
return
0
;
}
return
(
data
>>
8
)
|
((
data
&
0xff
)
<<
8
);
}
static
unsigned
int
wm8523_read
(
struct
snd_soc_codec
*
codec
,
unsigned
int
reg
)
{
u16
*
reg_cache
=
codec
->
reg_cache
;
BUG_ON
(
reg
>
WM8523_MAX_REGISTER
);
if
(
wm8523_volatile
(
reg
))
return
wm8523_read_hw
(
codec
,
reg
);
else
return
reg_cache
[
reg
];
return
snd_soc_write
(
codec
,
WM8523_DEVICE_ID
,
0
);
}
static
const
DECLARE_TLV_DB_SCALE
(
dac_tlv
,
-
10000
,
25
,
0
);
...
...
@@ -228,8 +166,8 @@ static int wm8523_hw_params(struct snd_pcm_substream *substream,
struct
snd_soc_codec
*
codec
=
socdev
->
card
->
codec
;
struct
wm8523_priv
*
wm8523
=
codec
->
private_data
;
int
i
;
u16
aifctrl1
=
wm8523
_read
(
codec
,
WM8523_AIF_CTRL1
);
u16
aifctrl2
=
wm8523
_read
(
codec
,
WM8523_AIF_CTRL2
);
u16
aifctrl1
=
snd_soc
_read
(
codec
,
WM8523_AIF_CTRL1
);
u16
aifctrl2
=
snd_soc
_read
(
codec
,
WM8523_AIF_CTRL2
);
/* Find a supported LRCLK ratio */
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
lrclk_ratios
);
i
++
)
{
...
...
@@ -263,8 +201,8 @@ static int wm8523_hw_params(struct snd_pcm_substream *substream,
break
;
}
wm8523
_write
(
codec
,
WM8523_AIF_CTRL1
,
aifctrl1
);
wm8523
_write
(
codec
,
WM8523_AIF_CTRL2
,
aifctrl2
);
snd_soc
_write
(
codec
,
WM8523_AIF_CTRL1
,
aifctrl1
);
snd_soc
_write
(
codec
,
WM8523_AIF_CTRL2
,
aifctrl2
);
return
0
;
}
...
...
@@ -322,7 +260,7 @@ static int wm8523_set_dai_fmt(struct snd_soc_dai *codec_dai,
unsigned
int
fmt
)
{
struct
snd_soc_codec
*
codec
=
codec_dai
->
codec
;
u16
aifctrl1
=
wm8523
_read
(
codec
,
WM8523_AIF_CTRL1
);
u16
aifctrl1
=
snd_soc
_read
(
codec
,
WM8523_AIF_CTRL1
);
aifctrl1
&=
~
(
WM8523_BCLK_INV_MASK
|
WM8523_LRCLK_INV_MASK
|
WM8523_FMT_MASK
|
WM8523_AIF_MSTR_MASK
);
...
...
@@ -372,7 +310,7 @@ static int wm8523_set_dai_fmt(struct snd_soc_dai *codec_dai,
return
-
EINVAL
;
}
wm8523
_write
(
codec
,
WM8523_AIF_CTRL1
,
aifctrl1
);
snd_soc
_write
(
codec
,
WM8523_AIF_CTRL1
,
aifctrl1
);
return
0
;
}
...
...
@@ -411,7 +349,7 @@ static int wm8523_set_bias_level(struct snd_soc_codec *codec,
/* Sync back default/cached values */
for
(
i
=
WM8523_AIF_CTRL1
;
i
<
WM8523_MAX_REGISTER
;
i
++
)
wm8523
_write
(
codec
,
i
,
wm8523
->
reg_cache
[
i
]);
snd_soc
_write
(
codec
,
i
,
wm8523
->
reg_cache
[
i
]);
msleep
(
100
);
...
...
@@ -543,7 +481,8 @@ struct snd_soc_codec_device soc_codec_dev_wm8523 = {
};
EXPORT_SYMBOL_GPL
(
soc_codec_dev_wm8523
);
static
int
wm8523_register
(
struct
wm8523_priv
*
wm8523
)
static
int
wm8523_register
(
struct
wm8523_priv
*
wm8523
,
enum
snd_soc_control_type
control
)
{
int
ret
;
struct
snd_soc_codec
*
codec
=
&
wm8523
->
codec
;
...
...
@@ -561,14 +500,13 @@ static int wm8523_register(struct wm8523_priv *wm8523)
codec
->
private_data
=
wm8523
;
codec
->
name
=
"WM8523"
;
codec
->
owner
=
THIS_MODULE
;
codec
->
read
=
wm8523_read
;
codec
->
write
=
wm8523_write
;
codec
->
bias_level
=
SND_SOC_BIAS_OFF
;
codec
->
set_bias_level
=
wm8523_set_bias_level
;
codec
->
dai
=
&
wm8523_dai
;
codec
->
num_dai
=
1
;
codec
->
reg_cache_size
=
WM8523_REGISTER_COUNT
;
codec
->
reg_cache
=
&
wm8523
->
reg_cache
;
codec
->
volatile_register
=
wm8523_volatile_register
;
wm8523
->
rate_constraint
.
list
=
&
wm8523
->
rate_constraint_list
[
0
];
wm8523
->
rate_constraint
.
count
=
...
...
@@ -576,6 +514,12 @@ static int wm8523_register(struct wm8523_priv *wm8523)
memcpy
(
codec
->
reg_cache
,
wm8523_reg
,
sizeof
(
wm8523_reg
));
ret
=
snd_soc_codec_set_cache_io
(
codec
,
8
,
16
,
control
);
if
(
ret
!=
0
)
{
dev_err
(
codec
->
dev
,
"Failed to set cache I/O: %d
\n
"
,
ret
);
goto
err
;
}
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
wm8523
->
supplies
);
i
++
)
wm8523
->
supplies
[
i
].
supply
=
wm8523_supply_names
[
i
];
...
...
@@ -593,7 +537,7 @@ static int wm8523_register(struct wm8523_priv *wm8523)
goto
err_get
;
}
ret
=
wm8523
_read
(
codec
,
WM8523_DEVICE_ID
);
ret
=
snd_soc
_read
(
codec
,
WM8523_DEVICE_ID
);
if
(
ret
<
0
)
{
dev_err
(
codec
->
dev
,
"Failed to read ID register
\n
"
);
goto
err_enable
;
...
...
@@ -604,7 +548,7 @@ static int wm8523_register(struct wm8523_priv *wm8523)
goto
err_enable
;
}
ret
=
wm8523
_read
(
codec
,
WM8523_REVISION
);
ret
=
snd_soc
_read
(
codec
,
WM8523_REVISION
);
if
(
ret
<
0
)
{
dev_err
(
codec
->
dev
,
"Failed to read revision register
\n
"
);
goto
err_enable
;
...
...
@@ -684,7 +628,7 @@ static __devinit int wm8523_i2c_probe(struct i2c_client *i2c,
codec
->
dev
=
&
i2c
->
dev
;
return
wm8523_register
(
wm8523
);
return
wm8523_register
(
wm8523
,
SND_SOC_I2C
);
}
static
__devexit
int
wm8523_i2c_remove
(
struct
i2c_client
*
client
)
...
...
sound/soc/codecs/wm8580.c
View file @
06cddefc
...
...
@@ -205,73 +205,6 @@ struct wm8580_priv {
struct
pll_state
b
;
};
/*
* read wm8580 register cache
*/
static
inline
unsigned
int
wm8580_read_reg_cache
(
struct
snd_soc_codec
*
codec
,
unsigned
int
reg
)
{
u16
*
cache
=
codec
->
reg_cache
;
BUG_ON
(
reg
>=
ARRAY_SIZE
(
wm8580_reg
));
return
cache
[
reg
];
}
/*
* write wm8580 register cache
*/
static
inline
void
wm8580_write_reg_cache
(
struct
snd_soc_codec
*
codec
,
unsigned
int
reg
,
unsigned
int
value
)
{
u16
*
cache
=
codec
->
reg_cache
;
cache
[
reg
]
=
value
;
}
/*
* write to the WM8580 register space
*/
static
int
wm8580_write
(
struct
snd_soc_codec
*
codec
,
unsigned
int
reg
,
unsigned
int
value
)
{
u8
data
[
2
];
BUG_ON
(
reg
>=
ARRAY_SIZE
(
wm8580_reg
));
/* Registers are 9 bits wide */
value
&=
0x1ff
;
switch
(
reg
)
{
case
WM8580_RESET
:
/* Uncached */
break
;
default:
if
(
value
==
wm8580_read_reg_cache
(
codec
,
reg
))
return
0
;
}
/* data is
* D15..D9 WM8580 register offset
* D8...D0 register data
*/
data
[
0
]
=
(
reg
<<
1
)
|
((
value
>>
8
)
&
0x0001
);
data
[
1
]
=
value
&
0x00ff
;
wm8580_write_reg_cache
(
codec
,
reg
,
value
);
if
(
codec
->
hw_write
(
codec
->
control_data
,
data
,
2
)
==
2
)
return
0
;
else
return
-
EIO
;
}
static
inline
unsigned
int
wm8580_read
(
struct
snd_soc_codec
*
codec
,
unsigned
int
reg
)
{
switch
(
reg
)
{
default:
return
wm8580_read_reg_cache
(
codec
,
reg
);
}
}
static
const
DECLARE_TLV_DB_SCALE
(
dac_tlv
,
-
12750
,
50
,
1
);
static
int
wm8580_out_vu
(
struct
snd_kcontrol
*
kcontrol
,
...
...
@@ -280,25 +213,22 @@ static int wm8580_out_vu(struct snd_kcontrol *kcontrol,
struct
soc_mixer_control
*
mc
=
(
struct
soc_mixer_control
*
)
kcontrol
->
private_value
;
struct
snd_soc_codec
*
codec
=
snd_kcontrol_chip
(
kcontrol
);
u16
*
reg_cache
=
codec
->
reg_cache
;
unsigned
int
reg
=
mc
->
reg
;
unsigned
int
reg2
=
mc
->
rreg
;
int
ret
;
u16
val
;
/* Clear the register cache so we write without VU set */
wm8580_write_reg_cache
(
codec
,
reg
,
0
)
;
wm8580_write_reg_cache
(
codec
,
reg2
,
0
)
;
reg_cache
[
reg
]
=
0
;
reg_cache
[
reg2
]
=
0
;
ret
=
snd_soc_put_volsw_2r
(
kcontrol
,
ucontrol
);
if
(
ret
<
0
)
return
ret
;
/* Now write again with the volume update bit set */
val
=
wm8580_read_reg_cache
(
codec
,
reg
);
wm8580_write
(
codec
,
reg
,
val
|
0x0100
);
val
=
wm8580_read_reg_cache
(
codec
,
reg2
);
wm8580_write
(
codec
,
reg2
,
val
|
0x0100
);
snd_soc_update_bits
(
codec
,
reg
,
0x100
,
0x100
);
snd_soc_update_bits
(
codec
,
reg2
,
0x100
,
0x100
);
return
0
;
}
...
...
@@ -521,27 +451,27 @@ static int wm8580_set_dai_pll(struct snd_soc_dai *codec_dai,
/* Always disable the PLL - it is not safe to leave it running
* while reprogramming it.
*/
reg
=
wm8580
_read
(
codec
,
WM8580_PWRDN2
);
wm8580
_write
(
codec
,
WM8580_PWRDN2
,
reg
|
pwr_mask
);
reg
=
snd_soc
_read
(
codec
,
WM8580_PWRDN2
);
snd_soc
_write
(
codec
,
WM8580_PWRDN2
,
reg
|
pwr_mask
);
if
(
!
freq_in
||
!
freq_out
)
return
0
;
wm8580
_write
(
codec
,
WM8580_PLLA1
+
offset
,
pll_div
.
k
&
0x1ff
);
wm8580
_write
(
codec
,
WM8580_PLLA2
+
offset
,
(
pll_div
.
k
>>
9
)
&
0xff
);
wm8580
_write
(
codec
,
WM8580_PLLA3
+
offset
,
snd_soc
_write
(
codec
,
WM8580_PLLA1
+
offset
,
pll_div
.
k
&
0x1ff
);
snd_soc
_write
(
codec
,
WM8580_PLLA2
+
offset
,
(
pll_div
.
k
>>
9
)
&
0xff
);
snd_soc
_write
(
codec
,
WM8580_PLLA3
+
offset
,
(
pll_div
.
k
>>
18
&
0xf
)
|
(
pll_div
.
n
<<
4
));
reg
=
wm8580
_read
(
codec
,
WM8580_PLLA4
+
offset
);
reg
=
snd_soc
_read
(
codec
,
WM8580_PLLA4
+
offset
);
reg
&=
~
0x3f
;
reg
|=
pll_div
.
prescale
|
pll_div
.
postscale
<<
1
|
pll_div
.
freqmode
<<
3
;
wm8580
_write
(
codec
,
WM8580_PLLA4
+
offset
,
reg
);
snd_soc
_write
(
codec
,
WM8580_PLLA4
+
offset
,
reg
);
/* All done, turn it on */
reg
=
wm8580
_read
(
codec
,
WM8580_PWRDN2
);
wm8580
_write
(
codec
,
WM8580_PWRDN2
,
reg
&
~
pwr_mask
);
reg
=
snd_soc
_read
(
codec
,
WM8580_PWRDN2
);
snd_soc
_write
(
codec
,
WM8580_PWRDN2
,
reg
&
~
pwr_mask
);
return
0
;
}
...
...
@@ -556,7 +486,7 @@ static int wm8580_paif_hw_params(struct snd_pcm_substream *substream,
struct
snd_soc_pcm_runtime
*
rtd
=
substream
->
private_data
;
struct
snd_soc_device
*
socdev
=
rtd
->
socdev
;
struct
snd_soc_codec
*
codec
=
socdev
->
card
->
codec
;
u16
paifb
=
wm8580
_read
(
codec
,
WM8580_PAIF3
+
dai
->
id
);
u16
paifb
=
snd_soc
_read
(
codec
,
WM8580_PAIF3
+
dai
->
id
);
paifb
&=
~
WM8580_AIF_LENGTH_MASK
;
/* bit size */
...
...
@@ -576,7 +506,7 @@ static int wm8580_paif_hw_params(struct snd_pcm_substream *substream,
return
-
EINVAL
;
}
wm8580
_write
(
codec
,
WM8580_PAIF3
+
dai
->
id
,
paifb
);
snd_soc
_write
(
codec
,
WM8580_PAIF3
+
dai
->
id
,
paifb
);
return
0
;
}
...
...
@@ -588,8 +518,8 @@ static int wm8580_set_paif_dai_fmt(struct snd_soc_dai *codec_dai,
unsigned
int
aifb
;
int
can_invert_lrclk
;
aifa
=
wm8580
_read
(
codec
,
WM8580_PAIF1
+
codec_dai
->
id
);
aifb
=
wm8580
_read
(
codec
,
WM8580_PAIF3
+
codec_dai
->
id
);
aifa
=
snd_soc
_read
(
codec
,
WM8580_PAIF1
+
codec_dai
->
id
);
aifb
=
snd_soc
_read
(
codec
,
WM8580_PAIF3
+
codec_dai
->
id
);
aifb
&=
~
(
WM8580_AIF_FMT_MASK
|
WM8580_AIF_LRP
|
WM8580_AIF_BCP
);
...
...
@@ -655,8 +585,8 @@ static int wm8580_set_paif_dai_fmt(struct snd_soc_dai *codec_dai,
return
-
EINVAL
;
}
wm8580
_write
(
codec
,
WM8580_PAIF1
+
codec_dai
->
id
,
aifa
);
wm8580
_write
(
codec
,
WM8580_PAIF3
+
codec_dai
->
id
,
aifb
);
snd_soc
_write
(
codec
,
WM8580_PAIF1
+
codec_dai
->
id
,
aifa
);
snd_soc
_write
(
codec
,
WM8580_PAIF3
+
codec_dai
->
id
,
aifb
);
return
0
;
}
...
...
@@ -669,7 +599,7 @@ static int wm8580_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
switch
(
div_id
)
{
case
WM8580_MCLK
:
reg
=
wm8580
_read
(
codec
,
WM8580_PLLB4
);
reg
=
snd_soc
_read
(
codec
,
WM8580_PLLB4
);
reg
&=
~
WM8580_PLLB4_MCLKOUTSRC_MASK
;
switch
(
div
)
{
...
...
@@ -691,11 +621,11 @@ static int wm8580_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
default:
return
-
EINVAL
;
}
wm8580
_write
(
codec
,
WM8580_PLLB4
,
reg
);
snd_soc
_write
(
codec
,
WM8580_PLLB4
,
reg
);
break
;
case
WM8580_DAC_CLKSEL
:
reg
=
wm8580
_read
(
codec
,
WM8580_CLKSEL
);
reg
=
snd_soc
_read
(
codec
,
WM8580_CLKSEL
);
reg
&=
~
WM8580_CLKSEL_DAC_CLKSEL_MASK
;
switch
(
div
)
{
...
...
@@ -713,11 +643,11 @@ static int wm8580_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
default:
return
-
EINVAL
;
}
wm8580
_write
(
codec
,
WM8580_CLKSEL
,
reg
);
snd_soc
_write
(
codec
,
WM8580_CLKSEL
,
reg
);
break
;
case
WM8580_CLKOUTSRC
:
reg
=
wm8580
_read
(
codec
,
WM8580_PLLB4
);
reg
=
snd_soc
_read
(
codec
,
WM8580_PLLB4
);
reg
&=
~
WM8580_PLLB4_CLKOUTSRC_MASK
;
switch
(
div
)
{
...
...
@@ -739,7 +669,7 @@ static int wm8580_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
default:
return
-
EINVAL
;
}
wm8580
_write
(
codec
,
WM8580_PLLB4
,
reg
);
snd_soc
_write
(
codec
,
WM8580_PLLB4
,
reg
);
break
;
default:
...
...
@@ -754,14 +684,14 @@ static int wm8580_digital_mute(struct snd_soc_dai *codec_dai, int mute)
struct
snd_soc_codec
*
codec
=
codec_dai
->
codec
;
unsigned
int
reg
;
reg
=
wm8580
_read
(
codec
,
WM8580_DAC_CONTROL5
);
reg
=
snd_soc
_read
(
codec
,
WM8580_DAC_CONTROL5
);
if
(
mute
)
reg
|=
WM8580_DAC_CONTROL5_MUTEALL
;
else
reg
&=
~
WM8580_DAC_CONTROL5_MUTEALL
;
wm8580
_write
(
codec
,
WM8580_DAC_CONTROL5
,
reg
);
snd_soc
_write
(
codec
,
WM8580_DAC_CONTROL5
,
reg
);
return
0
;
}
...
...
@@ -778,20 +708,20 @@ static int wm8580_set_bias_level(struct snd_soc_codec *codec,
case
SND_SOC_BIAS_STANDBY
:
if
(
codec
->
bias_level
==
SND_SOC_BIAS_OFF
)
{
/* Power up and get individual control of the DACs */
reg
=
wm8580
_read
(
codec
,
WM8580_PWRDN1
);
reg
=
snd_soc
_read
(
codec
,
WM8580_PWRDN1
);
reg
&=
~
(
WM8580_PWRDN1_PWDN
|
WM8580_PWRDN1_ALLDACPD
);
wm8580
_write
(
codec
,
WM8580_PWRDN1
,
reg
);
snd_soc
_write
(
codec
,
WM8580_PWRDN1
,
reg
);
/* Make VMID high impedence */
reg
=
wm8580
_read
(
codec
,
WM8580_ADC_CONTROL1
);
reg
=
snd_soc
_read
(
codec
,
WM8580_ADC_CONTROL1
);
reg
&=
~
0x100
;
wm8580
_write
(
codec
,
WM8580_ADC_CONTROL1
,
reg
);
snd_soc
_write
(
codec
,
WM8580_ADC_CONTROL1
,
reg
);
}
break
;
case
SND_SOC_BIAS_OFF
:
reg
=
wm8580
_read
(
codec
,
WM8580_PWRDN1
);
wm8580
_write
(
codec
,
WM8580_PWRDN1
,
reg
|
WM8580_PWRDN1_PWDN
);
reg
=
snd_soc
_read
(
codec
,
WM8580_PWRDN1
);
snd_soc
_write
(
codec
,
WM8580_PWRDN1
,
reg
|
WM8580_PWRDN1_PWDN
);
break
;
}
codec
->
bias_level
=
level
;
...
...
@@ -902,7 +832,8 @@ struct snd_soc_codec_device soc_codec_dev_wm8580 = {
};
EXPORT_SYMBOL_GPL
(
soc_codec_dev_wm8580
);
static
int
wm8580_register
(
struct
wm8580_priv
*
wm8580
)
static
int
wm8580_register
(
struct
wm8580_priv
*
wm8580
,
enum
snd_soc_control_type
control
)
{
int
ret
,
i
;
struct
snd_soc_codec
*
codec
=
&
wm8580
->
codec
;
...
...
@@ -920,8 +851,6 @@ static int wm8580_register(struct wm8580_priv *wm8580)
codec
->
private_data
=
wm8580
;
codec
->
name
=
"WM8580"
;
codec
->
owner
=
THIS_MODULE
;
codec
->
read
=
wm8580_read_reg_cache
;
codec
->
write
=
wm8580_write
;
codec
->
bias_level
=
SND_SOC_BIAS_OFF
;
codec
->
set_bias_level
=
wm8580_set_bias_level
;
codec
->
dai
=
wm8580_dai
;
...
...
@@ -931,6 +860,12 @@ static int wm8580_register(struct wm8580_priv *wm8580)
memcpy
(
codec
->
reg_cache
,
wm8580_reg
,
sizeof
(
wm8580_reg
));
ret
=
snd_soc_codec_set_cache_io
(
codec
,
7
,
9
,
control
);
if
(
ret
<
0
)
{
dev_err
(
codec
->
dev
,
"Failed to set cache I/O: %d
\n
"
,
ret
);
goto
err
;
}
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
wm8580
->
supplies
);
i
++
)
wm8580
->
supplies
[
i
].
supply
=
wm8580_supply_names
[
i
];
...
...
@@ -949,7 +884,7 @@ static int wm8580_register(struct wm8580_priv *wm8580)
}
/* Get the codec into a known state */
ret
=
wm8580
_write
(
codec
,
WM8580_RESET
,
0
);
ret
=
snd_soc
_write
(
codec
,
WM8580_RESET
,
0
);
if
(
ret
!=
0
)
{
dev_err
(
codec
->
dev
,
"Failed to reset codec: %d
\n
"
,
ret
);
goto
err_regulator_enable
;
...
...
@@ -1010,14 +945,13 @@ static int wm8580_i2c_probe(struct i2c_client *i2c,
return
-
ENOMEM
;
codec
=
&
wm8580
->
codec
;
codec
->
hw_write
=
(
hw_write_t
)
i2c_master_send
;
i2c_set_clientdata
(
i2c
,
wm8580
);
codec
->
control_data
=
i2c
;
codec
->
dev
=
&
i2c
->
dev
;
return
wm8580_register
(
wm8580
);
return
wm8580_register
(
wm8580
,
SND_SOC_I2C
);
}
static
int
wm8580_i2c_remove
(
struct
i2c_client
*
client
)
...
...
sound/soc/codecs/wm8728.c
View file @
06cddefc
...
...
@@ -43,45 +43,6 @@ static const u16 wm8728_reg_defaults[] = {
0x100
,
};
static
inline
unsigned
int
wm8728_read_reg_cache
(
struct
snd_soc_codec
*
codec
,
unsigned
int
reg
)
{
u16
*
cache
=
codec
->
reg_cache
;
BUG_ON
(
reg
>=
ARRAY_SIZE
(
wm8728_reg_defaults
));
return
cache
[
reg
];
}
static
inline
void
wm8728_write_reg_cache
(
struct
snd_soc_codec
*
codec
,
u16
reg
,
unsigned
int
value
)
{
u16
*
cache
=
codec
->
reg_cache
;
BUG_ON
(
reg
>=
ARRAY_SIZE
(
wm8728_reg_defaults
));
cache
[
reg
]
=
value
;
}
/*
* write to the WM8728 register space
*/
static
int
wm8728_write
(
struct
snd_soc_codec
*
codec
,
unsigned
int
reg
,
unsigned
int
value
)
{
u8
data
[
2
];
/* data is
* D15..D9 WM8728 register offset
* D8...D0 register data
*/
data
[
0
]
=
(
reg
<<
1
)
|
((
value
>>
8
)
&
0x0001
);
data
[
1
]
=
value
&
0x00ff
;
wm8728_write_reg_cache
(
codec
,
reg
,
value
);
if
(
codec
->
hw_write
(
codec
->
control_data
,
data
,
2
)
==
2
)
return
0
;
else
return
-
EIO
;
}
static
const
DECLARE_TLV_DB_SCALE
(
wm8728_tlv
,
-
12750
,
50
,
1
);
static
const
struct
snd_kcontrol_new
wm8728_snd_controls
[]
=
{
...
...
@@ -121,12 +82,12 @@ static int wm8728_add_widgets(struct snd_soc_codec *codec)
static
int
wm8728_mute
(
struct
snd_soc_dai
*
dai
,
int
mute
)
{
struct
snd_soc_codec
*
codec
=
dai
->
codec
;
u16
mute_reg
=
wm8728_read_reg_cache
(
codec
,
WM8728_DACCTL
);
u16
mute_reg
=
snd_soc_read
(
codec
,
WM8728_DACCTL
);
if
(
mute
)
wm8728
_write
(
codec
,
WM8728_DACCTL
,
mute_reg
|
1
);
snd_soc
_write
(
codec
,
WM8728_DACCTL
,
mute_reg
|
1
);
else
wm8728
_write
(
codec
,
WM8728_DACCTL
,
mute_reg
&
~
1
);
snd_soc
_write
(
codec
,
WM8728_DACCTL
,
mute_reg
&
~
1
);
return
0
;
}
...
...
@@ -138,7 +99,7 @@ static int wm8728_hw_params(struct snd_pcm_substream *substream,
struct
snd_soc_pcm_runtime
*
rtd
=
substream
->
private_data
;
struct
snd_soc_device
*
socdev
=
rtd
->
socdev
;
struct
snd_soc_codec
*
codec
=
socdev
->
card
->
codec
;
u16
dac
=
wm8728_read_reg_cache
(
codec
,
WM8728_DACCTL
);
u16
dac
=
snd_soc_read
(
codec
,
WM8728_DACCTL
);
dac
&=
~
0x18
;
...
...
@@ -155,7 +116,7 @@ static int wm8728_hw_params(struct snd_pcm_substream *substream,
return
-
EINVAL
;
}
wm8728
_write
(
codec
,
WM8728_DACCTL
,
dac
);
snd_soc
_write
(
codec
,
WM8728_DACCTL
,
dac
);
return
0
;
}
...
...
@@ -164,7 +125,7 @@ static int wm8728_set_dai_fmt(struct snd_soc_dai *codec_dai,
unsigned
int
fmt
)
{
struct
snd_soc_codec
*
codec
=
codec_dai
->
codec
;
u16
iface
=
wm8728_read_reg_cache
(
codec
,
WM8728_IFCTL
);
u16
iface
=
snd_soc_read
(
codec
,
WM8728_IFCTL
);
/* Currently only I2S is supported by the driver, though the
* hardware is more flexible.
...
...
@@ -204,7 +165,7 @@ static int wm8728_set_dai_fmt(struct snd_soc_dai *codec_dai,
return
-
EINVAL
;
}
wm8728
_write
(
codec
,
WM8728_IFCTL
,
iface
);
snd_soc
_write
(
codec
,
WM8728_IFCTL
,
iface
);
return
0
;
}
...
...
@@ -220,19 +181,19 @@ static int wm8728_set_bias_level(struct snd_soc_codec *codec,
case
SND_SOC_BIAS_STANDBY
:
if
(
codec
->
bias_level
==
SND_SOC_BIAS_OFF
)
{
/* Power everything up... */
reg
=
wm8728_read_reg_cache
(
codec
,
WM8728_DACCTL
);
wm8728
_write
(
codec
,
WM8728_DACCTL
,
reg
&
~
0x4
);
reg
=
snd_soc_read
(
codec
,
WM8728_DACCTL
);
snd_soc
_write
(
codec
,
WM8728_DACCTL
,
reg
&
~
0x4
);
/* ..then sync in the register cache. */
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
wm8728_reg_defaults
);
i
++
)
wm8728
_write
(
codec
,
i
,
wm8728_read_reg_cache
(
codec
,
i
));
snd_soc
_write
(
codec
,
i
,
snd_soc_read
(
codec
,
i
));
}
break
;
case
SND_SOC_BIAS_OFF
:
reg
=
wm8728_read_reg_cache
(
codec
,
WM8728_DACCTL
);
wm8728
_write
(
codec
,
WM8728_DACCTL
,
reg
|
0x4
);
reg
=
snd_soc_read
(
codec
,
WM8728_DACCTL
);
snd_soc
_write
(
codec
,
WM8728_DACCTL
,
reg
|
0x4
);
break
;
}
codec
->
bias_level
=
level
;
...
...
@@ -287,15 +248,14 @@ static int wm8728_resume(struct platform_device *pdev)
* initialise the WM8728 driver
* register the mixer and dsp interfaces with the kernel
*/
static
int
wm8728_init
(
struct
snd_soc_device
*
socdev
)
static
int
wm8728_init
(
struct
snd_soc_device
*
socdev
,
enum
snd_soc_control_type
control
)
{
struct
snd_soc_codec
*
codec
=
socdev
->
card
->
codec
;
int
ret
=
0
;
codec
->
name
=
"WM8728"
;
codec
->
owner
=
THIS_MODULE
;
codec
->
read
=
wm8728_read_reg_cache
;
codec
->
write
=
wm8728_write
;
codec
->
set_bias_level
=
wm8728_set_bias_level
;
codec
->
dai
=
&
wm8728_dai
;
codec
->
num_dai
=
1
;
...
...
@@ -307,11 +267,18 @@ static int wm8728_init(struct snd_soc_device *socdev)
if
(
codec
->
reg_cache
==
NULL
)
return
-
ENOMEM
;
ret
=
snd_soc_codec_set_cache_io
(
codec
,
7
,
9
,
control
);
if
(
ret
<
0
)
{
printk
(
KERN_ERR
"wm8728: failed to configure cache I/O: %d
\n
"
,
ret
);
goto
err
;
}
/* register pcms */
ret
=
snd_soc_new_pcms
(
socdev
,
SNDRV_DEFAULT_IDX1
,
SNDRV_DEFAULT_STR1
);
if
(
ret
<
0
)
{
printk
(
KERN_ERR
"wm8728: failed to create pcms
\n
"
);
goto
pcm_
err
;
goto
err
;
}
/* power on device */
...
...
@@ -331,7 +298,7 @@ static int wm8728_init(struct snd_soc_device *socdev)
card_err:
snd_soc_free_pcms
(
socdev
);
snd_soc_dapm_free
(
socdev
);
pcm_
err:
err:
kfree
(
codec
->
reg_cache
);
return
ret
;
}
...
...
@@ -357,7 +324,7 @@ static int wm8728_i2c_probe(struct i2c_client *i2c,
i2c_set_clientdata
(
i2c
,
codec
);
codec
->
control_data
=
i2c
;
ret
=
wm8728_init
(
socdev
);
ret
=
wm8728_init
(
socdev
,
SND_SOC_I2C
);
if
(
ret
<
0
)
pr_err
(
"failed to initialise WM8728
\n
"
);
...
...
@@ -437,7 +404,7 @@ static int __devinit wm8728_spi_probe(struct spi_device *spi)
codec
->
control_data
=
spi
;
ret
=
wm8728_init
(
socdev
);
ret
=
wm8728_init
(
socdev
,
SND_SOC_SPI
);
if
(
ret
<
0
)
dev_err
(
&
spi
->
dev
,
"failed to initialise WM8728
\n
"
);
...
...
@@ -458,30 +425,6 @@ static struct spi_driver wm8728_spi_driver = {
.
probe
=
wm8728_spi_probe
,
.
remove
=
__devexit_p
(
wm8728_spi_remove
),
};
static
int
wm8728_spi_write
(
struct
spi_device
*
spi
,
const
char
*
data
,
int
len
)
{
struct
spi_transfer
t
;
struct
spi_message
m
;
u8
msg
[
2
];
if
(
len
<=
0
)
return
0
;
msg
[
0
]
=
data
[
0
];
msg
[
1
]
=
data
[
1
];
spi_message_init
(
&
m
);
memset
(
&
t
,
0
,
(
sizeof
t
));
t
.
tx_buf
=
&
msg
[
0
];
t
.
len
=
len
;
spi_message_add_tail
(
&
t
,
&
m
);
spi_sync
(
spi
,
&
m
);
return
len
;
}
#endif
/* CONFIG_SPI_MASTER */
static
int
wm8728_probe
(
struct
platform_device
*
pdev
)
...
...
@@ -506,13 +449,11 @@ static int wm8728_probe(struct platform_device *pdev)
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
if
(
setup
->
i2c_address
)
{
codec
->
hw_write
=
(
hw_write_t
)
i2c_master_send
;
ret
=
wm8728_add_i2c_device
(
pdev
,
setup
);
}
#endif
#if defined(CONFIG_SPI_MASTER)
if
(
setup
->
spi
)
{
codec
->
hw_write
=
(
hw_write_t
)
wm8728_spi_write
;
ret
=
spi_register_driver
(
&
wm8728_spi_driver
);
if
(
ret
!=
0
)
printk
(
KERN_ERR
"can't add spi driver"
);
...
...
sound/soc/codecs/wm8731.c
View file @
06cddefc
...
...
@@ -51,60 +51,12 @@ static int wm8731_spi_write(struct spi_device *spi, const char *data, int len);
* There is no point in caching the reset register
*/
static
const
u16
wm8731_reg
[
WM8731_CACHEREGNUM
]
=
{
0x0097
,
0x0097
,
0x0079
,
0x0079
,
0x000a
,
0x0008
,
0x009f
,
0x000a
,
0x0000
,
0x0000
0x0097
,
0x0097
,
0x0079
,
0x0079
,
0x000a
,
0x0008
,
0x009f
,
0x000a
,
0x0000
,
0x0000
};
/*
* read wm8731 register cache
*/
static
inline
unsigned
int
wm8731_read_reg_cache
(
struct
snd_soc_codec
*
codec
,
unsigned
int
reg
)
{
u16
*
cache
=
codec
->
reg_cache
;
if
(
reg
==
WM8731_RESET
)
return
0
;
if
(
reg
>=
WM8731_CACHEREGNUM
)
return
-
1
;
return
cache
[
reg
];
}
/*
* write wm8731 register cache
*/
static
inline
void
wm8731_write_reg_cache
(
struct
snd_soc_codec
*
codec
,
u16
reg
,
unsigned
int
value
)
{
u16
*
cache
=
codec
->
reg_cache
;
if
(
reg
>=
WM8731_CACHEREGNUM
)
return
;
cache
[
reg
]
=
value
;
}
/*
* write to the WM8731 register space
*/
static
int
wm8731_write
(
struct
snd_soc_codec
*
codec
,
unsigned
int
reg
,
unsigned
int
value
)
{
u8
data
[
2
];
/* data is
* D15..D9 WM8731 register offset
* D8...D0 register data
*/
data
[
0
]
=
(
reg
<<
1
)
|
((
value
>>
8
)
&
0x0001
);
data
[
1
]
=
value
&
0x00ff
;
wm8731_write_reg_cache
(
codec
,
reg
,
value
);
if
(
codec
->
hw_write
(
codec
->
control_data
,
data
,
2
)
==
2
)
return
0
;
else
return
-
EIO
;
}
#define wm8731_reset(c) wm8731_write(c, WM8731_RESET, 0)
#define wm8731_reset(c) snd_soc_write(c, WM8731_RESET, 0)
static
const
char
*
wm8731_input_select
[]
=
{
"Line In"
,
"Mic"
};
static
const
char
*
wm8731_deemph
[]
=
{
"None"
,
"32Khz"
,
"44.1Khz"
,
"48Khz"
};
...
...
@@ -267,12 +219,12 @@ static int wm8731_hw_params(struct snd_pcm_substream *substream,
struct
snd_soc_device
*
socdev
=
rtd
->
socdev
;
struct
snd_soc_codec
*
codec
=
socdev
->
card
->
codec
;
struct
wm8731_priv
*
wm8731
=
codec
->
private_data
;
u16
iface
=
wm8731_read_reg_cache
(
codec
,
WM8731_IFACE
)
&
0xfff3
;
u16
iface
=
snd_soc_read
(
codec
,
WM8731_IFACE
)
&
0xfff3
;
int
i
=
get_coeff
(
wm8731
->
sysclk
,
params_rate
(
params
));
u16
srate
=
(
coeff_div
[
i
].
sr
<<
2
)
|
(
coeff_div
[
i
].
bosr
<<
1
)
|
coeff_div
[
i
].
usb
;
wm8731
_write
(
codec
,
WM8731_SRATE
,
srate
);
snd_soc
_write
(
codec
,
WM8731_SRATE
,
srate
);
/* bit size */
switch
(
params_format
(
params
))
{
...
...
@@ -286,7 +238,7 @@ static int wm8731_hw_params(struct snd_pcm_substream *substream,
break
;
}
wm8731
_write
(
codec
,
WM8731_IFACE
,
iface
);
snd_soc
_write
(
codec
,
WM8731_IFACE
,
iface
);
return
0
;
}
...
...
@@ -298,7 +250,7 @@ static int wm8731_pcm_prepare(struct snd_pcm_substream *substream,
struct
snd_soc_codec
*
codec
=
socdev
->
card
->
codec
;
/* set active */
wm8731
_write
(
codec
,
WM8731_ACTIVE
,
0x0001
);
snd_soc
_write
(
codec
,
WM8731_ACTIVE
,
0x0001
);
return
0
;
}
...
...
@@ -313,19 +265,19 @@ static void wm8731_shutdown(struct snd_pcm_substream *substream,
/* deactivate */
if
(
!
codec
->
active
)
{
udelay
(
50
);
wm8731
_write
(
codec
,
WM8731_ACTIVE
,
0x0
);
snd_soc
_write
(
codec
,
WM8731_ACTIVE
,
0x0
);
}
}
static
int
wm8731_mute
(
struct
snd_soc_dai
*
dai
,
int
mute
)
{
struct
snd_soc_codec
*
codec
=
dai
->
codec
;
u16
mute_reg
=
wm8731_read_reg_cache
(
codec
,
WM8731_APDIGI
)
&
0xfff7
;
u16
mute_reg
=
snd_soc_read
(
codec
,
WM8731_APDIGI
)
&
0xfff7
;
if
(
mute
)
wm8731
_write
(
codec
,
WM8731_APDIGI
,
mute_reg
|
0x8
);
snd_soc
_write
(
codec
,
WM8731_APDIGI
,
mute_reg
|
0x8
);
else
wm8731
_write
(
codec
,
WM8731_APDIGI
,
mute_reg
);
snd_soc
_write
(
codec
,
WM8731_APDIGI
,
mute_reg
);
return
0
;
}
...
...
@@ -403,7 +355,7 @@ static int wm8731_set_dai_fmt(struct snd_soc_dai *codec_dai,
}
/* set iface */
wm8731
_write
(
codec
,
WM8731_IFACE
,
iface
);
snd_soc
_write
(
codec
,
WM8731_IFACE
,
iface
);
return
0
;
}
...
...
@@ -419,12 +371,12 @@ static int wm8731_set_bias_level(struct snd_soc_codec *codec,
break
;
case
SND_SOC_BIAS_STANDBY
:
/* Clear PWROFF, gate CLKOUT, everything else as-is */
reg
=
wm8731_read_reg_cache
(
codec
,
WM8731_PWR
)
&
0xff7f
;
wm8731
_write
(
codec
,
WM8731_PWR
,
reg
|
0x0040
);
reg
=
snd_soc_read
(
codec
,
WM8731_PWR
)
&
0xff7f
;
snd_soc
_write
(
codec
,
WM8731_PWR
,
reg
|
0x0040
);
break
;
case
SND_SOC_BIAS_OFF
:
wm8731
_write
(
codec
,
WM8731_ACTIVE
,
0x0
);
wm8731
_write
(
codec
,
WM8731_PWR
,
0xffff
);
snd_soc
_write
(
codec
,
WM8731_ACTIVE
,
0x0
);
snd_soc
_write
(
codec
,
WM8731_PWR
,
0xffff
);
break
;
}
codec
->
bias_level
=
level
;
...
...
@@ -474,7 +426,7 @@ static int wm8731_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
;
wm8731
_write
(
codec
,
WM8731_ACTIVE
,
0x0
);
snd_soc
_write
(
codec
,
WM8731_ACTIVE
,
0x0
);
wm8731_set_bias_level
(
codec
,
SND_SOC_BIAS_OFF
);
return
0
;
}
...
...
@@ -560,11 +512,11 @@ struct snd_soc_codec_device soc_codec_dev_wm8731 = {
};
EXPORT_SYMBOL_GPL
(
soc_codec_dev_wm8731
);
static
int
wm8731_register
(
struct
wm8731_priv
*
wm8731
)
static
int
wm8731_register
(
struct
wm8731_priv
*
wm8731
,
enum
snd_soc_control_type
control
)
{
int
ret
;
struct
snd_soc_codec
*
codec
=
&
wm8731
->
codec
;
u16
reg
;
if
(
wm8731_codec
)
{
dev_err
(
codec
->
dev
,
"Another WM8731 is registered
\n
"
);
...
...
@@ -579,8 +531,6 @@ static int wm8731_register(struct wm8731_priv *wm8731)
codec
->
private_data
=
wm8731
;
codec
->
name
=
"WM8731"
;
codec
->
owner
=
THIS_MODULE
;
codec
->
read
=
wm8731_read_reg_cache
;
codec
->
write
=
wm8731_write
;
codec
->
bias_level
=
SND_SOC_BIAS_OFF
;
codec
->
set_bias_level
=
wm8731_set_bias_level
;
codec
->
dai
=
&
wm8731_dai
;
...
...
@@ -590,6 +540,12 @@ static int wm8731_register(struct wm8731_priv *wm8731)
memcpy
(
codec
->
reg_cache
,
wm8731_reg
,
sizeof
(
wm8731_reg
));
ret
=
snd_soc_codec_set_cache_io
(
codec
,
7
,
9
,
control
);
if
(
ret
<
0
)
{
dev_err
(
codec
->
dev
,
"Failed to set cache I/O: %d
\n
"
,
ret
);
goto
err
;
}
ret
=
wm8731_reset
(
codec
);
if
(
ret
<
0
)
{
dev_err
(
codec
->
dev
,
"Failed to issue reset: %d
\n
"
,
ret
);
...
...
@@ -601,18 +557,13 @@ static int wm8731_register(struct wm8731_priv *wm8731)
wm8731_set_bias_level
(
codec
,
SND_SOC_BIAS_STANDBY
);
/* Latch the update bits */
reg
=
wm8731_read_reg_cache
(
codec
,
WM8731_LOUT1V
);
wm8731_write
(
codec
,
WM8731_LOUT1V
,
reg
&
~
0x0100
);
reg
=
wm8731_read_reg_cache
(
codec
,
WM8731_ROUT1V
);
wm8731_write
(
codec
,
WM8731_ROUT1V
,
reg
&
~
0x0100
);
reg
=
wm8731_read_reg_cache
(
codec
,
WM8731_LINVOL
);
wm8731_write
(
codec
,
WM8731_LINVOL
,
reg
&
~
0x0100
);
reg
=
wm8731_read_reg_cache
(
codec
,
WM8731_RINVOL
);
wm8731_write
(
codec
,
WM8731_RINVOL
,
reg
&
~
0x0100
);
snd_soc_update_bits
(
codec
,
WM8731_LOUT1V
,
0x100
,
0
);
snd_soc_update_bits
(
codec
,
WM8731_ROUT1V
,
0x100
,
0
);
snd_soc_update_bits
(
codec
,
WM8731_LINVOL
,
0x100
,
0
);
snd_soc_update_bits
(
codec
,
WM8731_RINVOL
,
0x100
,
0
);
/* Disable bypass path by default */
reg
=
wm8731_read_reg_cache
(
codec
,
WM8731_APANA
);
wm8731_write
(
codec
,
WM8731_APANA
,
reg
&
~
0x4
);
snd_soc_update_bits
(
codec
,
WM8731_APANA
,
0x4
,
0
);
wm8731_codec
=
codec
;
...
...
@@ -648,30 +599,6 @@ static void wm8731_unregister(struct wm8731_priv *wm8731)
}
#if defined(CONFIG_SPI_MASTER)
static
int
wm8731_spi_write
(
struct
spi_device
*
spi
,
const
char
*
data
,
int
len
)
{
struct
spi_transfer
t
;
struct
spi_message
m
;
u8
msg
[
2
];
if
(
len
<=
0
)
return
0
;
msg
[
0
]
=
data
[
0
];
msg
[
1
]
=
data
[
1
];
spi_message_init
(
&
m
);
memset
(
&
t
,
0
,
(
sizeof
t
));
t
.
tx_buf
=
&
msg
[
0
];
t
.
len
=
len
;
spi_message_add_tail
(
&
t
,
&
m
);
spi_sync
(
spi
,
&
m
);
return
len
;
}
static
int
__devinit
wm8731_spi_probe
(
struct
spi_device
*
spi
)
{
struct
snd_soc_codec
*
codec
;
...
...
@@ -683,12 +610,11 @@ static int __devinit wm8731_spi_probe(struct spi_device *spi)
codec
=
&
wm8731
->
codec
;
codec
->
control_data
=
spi
;
codec
->
hw_write
=
(
hw_write_t
)
wm8731_spi_write
;
codec
->
dev
=
&
spi
->
dev
;
dev_set_drvdata
(
&
spi
->
dev
,
wm8731
);
return
wm8731_register
(
wm8731
);
return
wm8731_register
(
wm8731
,
SND_SOC_SPI
);
}
static
int
__devexit
wm8731_spi_remove
(
struct
spi_device
*
spi
)
...
...
@@ -740,14 +666,13 @@ static __devinit int wm8731_i2c_probe(struct i2c_client *i2c,
return
-
ENOMEM
;
codec
=
&
wm8731
->
codec
;
codec
->
hw_write
=
(
hw_write_t
)
i2c_master_send
;
i2c_set_clientdata
(
i2c
,
wm8731
);
codec
->
control_data
=
i2c
;
codec
->
dev
=
&
i2c
->
dev
;
return
wm8731_register
(
wm8731
);
return
wm8731_register
(
wm8731
,
SND_SOC_I2C
);
}
static
__devexit
int
wm8731_i2c_remove
(
struct
i2c_client
*
client
)
...
...
sound/soc/codecs/wm8750.c
View file @
06cddefc
...
...
@@ -55,50 +55,7 @@ static const u16 wm8750_reg[] = {
0x0079
,
0x0079
,
0x0079
,
/* 40 */
};
/*
* read wm8750 register cache
*/
static
inline
unsigned
int
wm8750_read_reg_cache
(
struct
snd_soc_codec
*
codec
,
unsigned
int
reg
)
{
u16
*
cache
=
codec
->
reg_cache
;
if
(
reg
>
WM8750_CACHE_REGNUM
)
return
-
1
;
return
cache
[
reg
];
}
/*
* write wm8750 register cache
*/
static
inline
void
wm8750_write_reg_cache
(
struct
snd_soc_codec
*
codec
,
unsigned
int
reg
,
unsigned
int
value
)
{
u16
*
cache
=
codec
->
reg_cache
;
if
(
reg
>
WM8750_CACHE_REGNUM
)
return
;
cache
[
reg
]
=
value
;
}
static
int
wm8750_write
(
struct
snd_soc_codec
*
codec
,
unsigned
int
reg
,
unsigned
int
value
)
{
u8
data
[
2
];
/* data is
* D15..D9 WM8753 register offset
* D8...D0 register data
*/
data
[
0
]
=
(
reg
<<
1
)
|
((
value
>>
8
)
&
0x0001
);
data
[
1
]
=
value
&
0x00ff
;
wm8750_write_reg_cache
(
codec
,
reg
,
value
);
if
(
codec
->
hw_write
(
codec
->
control_data
,
data
,
2
)
==
2
)
return
0
;
else
return
-
EIO
;
}
#define wm8750_reset(c) wm8750_write(c, WM8750_RESET, 0)
#define wm8750_reset(c) snd_soc_write(c, WM8750_RESET, 0)
/*
* WM8750 Controls
...
...
@@ -594,7 +551,7 @@ static int wm8750_set_dai_fmt(struct snd_soc_dai *codec_dai,
return
-
EINVAL
;
}
wm8750
_write
(
codec
,
WM8750_IFACE
,
iface
);
snd_soc
_write
(
codec
,
WM8750_IFACE
,
iface
);
return
0
;
}
...
...
@@ -606,8 +563,8 @@ static int wm8750_pcm_hw_params(struct snd_pcm_substream *substream,
struct
snd_soc_device
*
socdev
=
rtd
->
socdev
;
struct
snd_soc_codec
*
codec
=
socdev
->
card
->
codec
;
struct
wm8750_priv
*
wm8750
=
codec
->
private_data
;
u16
iface
=
wm8750_read_reg_cache
(
codec
,
WM8750_IFACE
)
&
0x1f3
;
u16
srate
=
wm8750_read_reg_cache
(
codec
,
WM8750_SRATE
)
&
0x1c0
;
u16
iface
=
snd_soc_read
(
codec
,
WM8750_IFACE
)
&
0x1f3
;
u16
srate
=
snd_soc_read
(
codec
,
WM8750_SRATE
)
&
0x1c0
;
int
coeff
=
get_coeff
(
wm8750
->
sysclk
,
params_rate
(
params
));
/* bit size */
...
...
@@ -626,9 +583,9 @@ static int wm8750_pcm_hw_params(struct snd_pcm_substream *substream,
}
/* set iface & srate */
wm8750
_write
(
codec
,
WM8750_IFACE
,
iface
);
snd_soc
_write
(
codec
,
WM8750_IFACE
,
iface
);
if
(
coeff
>=
0
)
wm8750
_write
(
codec
,
WM8750_SRATE
,
srate
|
snd_soc
_write
(
codec
,
WM8750_SRATE
,
srate
|
(
coeff_div
[
coeff
].
sr
<<
1
)
|
coeff_div
[
coeff
].
usb
);
return
0
;
...
...
@@ -637,35 +594,35 @@ static int wm8750_pcm_hw_params(struct snd_pcm_substream *substream,
static
int
wm8750_mute
(
struct
snd_soc_dai
*
dai
,
int
mute
)
{
struct
snd_soc_codec
*
codec
=
dai
->
codec
;
u16
mute_reg
=
wm8750_read_reg_cache
(
codec
,
WM8750_ADCDAC
)
&
0xfff7
;
u16
mute_reg
=
snd_soc_read
(
codec
,
WM8750_ADCDAC
)
&
0xfff7
;
if
(
mute
)
wm8750
_write
(
codec
,
WM8750_ADCDAC
,
mute_reg
|
0x8
);
snd_soc
_write
(
codec
,
WM8750_ADCDAC
,
mute_reg
|
0x8
);
else
wm8750
_write
(
codec
,
WM8750_ADCDAC
,
mute_reg
);
snd_soc
_write
(
codec
,
WM8750_ADCDAC
,
mute_reg
);
return
0
;
}
static
int
wm8750_set_bias_level
(
struct
snd_soc_codec
*
codec
,
enum
snd_soc_bias_level
level
)
{
u16
pwr_reg
=
wm8750_read_reg_cache
(
codec
,
WM8750_PWR1
)
&
0xfe3e
;
u16
pwr_reg
=
snd_soc_read
(
codec
,
WM8750_PWR1
)
&
0xfe3e
;
switch
(
level
)
{
case
SND_SOC_BIAS_ON
:
/* set vmid to 50k and unmute dac */
wm8750
_write
(
codec
,
WM8750_PWR1
,
pwr_reg
|
0x00c0
);
snd_soc
_write
(
codec
,
WM8750_PWR1
,
pwr_reg
|
0x00c0
);
break
;
case
SND_SOC_BIAS_PREPARE
:
/* set vmid to 5k for quick power up */
wm8750
_write
(
codec
,
WM8750_PWR1
,
pwr_reg
|
0x01c1
);
snd_soc
_write
(
codec
,
WM8750_PWR1
,
pwr_reg
|
0x01c1
);
break
;
case
SND_SOC_BIAS_STANDBY
:
/* mute dac and set vmid to 500k, enable VREF */
wm8750
_write
(
codec
,
WM8750_PWR1
,
pwr_reg
|
0x0141
);
snd_soc
_write
(
codec
,
WM8750_PWR1
,
pwr_reg
|
0x0141
);
break
;
case
SND_SOC_BIAS_OFF
:
wm8750
_write
(
codec
,
WM8750_PWR1
,
0x0001
);
snd_soc
_write
(
codec
,
WM8750_PWR1
,
0x0001
);
break
;
}
codec
->
bias_level
=
level
;
...
...
@@ -754,15 +711,14 @@ static int wm8750_resume(struct platform_device *pdev)
* initialise the WM8750 driver
* register the mixer and dsp interfaces with the kernel
*/
static
int
wm8750_init
(
struct
snd_soc_device
*
socdev
)
static
int
wm8750_init
(
struct
snd_soc_device
*
socdev
,
enum
snd_soc_control_type
control
)
{
struct
snd_soc_codec
*
codec
=
socdev
->
card
->
codec
;
int
reg
,
ret
=
0
;
codec
->
name
=
"WM8750"
;
codec
->
owner
=
THIS_MODULE
;
codec
->
read
=
wm8750_read_reg_cache
;
codec
->
write
=
wm8750_write
;
codec
->
set_bias_level
=
wm8750_set_bias_level
;
codec
->
dai
=
&
wm8750_dai
;
codec
->
num_dai
=
1
;
...
...
@@ -771,13 +727,23 @@ static int wm8750_init(struct snd_soc_device *socdev)
if
(
codec
->
reg_cache
==
NULL
)
return
-
ENOMEM
;
wm8750_reset
(
codec
);
ret
=
snd_soc_codec_set_cache_io
(
codec
,
7
,
9
,
control
);
if
(
ret
<
0
)
{
printk
(
KERN_ERR
"wm8750: failed to set cache I/O: %d
\n
"
,
ret
);
goto
err
;
}
ret
=
wm8750_reset
(
codec
);
if
(
ret
<
0
)
{
printk
(
KERN_ERR
"wm8750: failed to reset: %d
\n
"
,
ret
);
goto
err
;
}
/* register pcms */
ret
=
snd_soc_new_pcms
(
socdev
,
SNDRV_DEFAULT_IDX1
,
SNDRV_DEFAULT_STR1
);
if
(
ret
<
0
)
{
printk
(
KERN_ERR
"wm8750: failed to create pcms
\n
"
);
goto
pcm_
err
;
goto
err
;
}
/* charge output caps */
...
...
@@ -786,22 +752,22 @@ static int wm8750_init(struct snd_soc_device *socdev)
schedule_delayed_work
(
&
codec
->
delayed_work
,
msecs_to_jiffies
(
1000
));
/* set the update bits */
reg
=
wm8750_read_reg_cache
(
codec
,
WM8750_LDAC
);
wm8750
_write
(
codec
,
WM8750_LDAC
,
reg
|
0x0100
);
reg
=
wm8750_read_reg_cache
(
codec
,
WM8750_RDAC
);
wm8750
_write
(
codec
,
WM8750_RDAC
,
reg
|
0x0100
);
reg
=
wm8750_read_reg_cache
(
codec
,
WM8750_LOUT1V
);
wm8750
_write
(
codec
,
WM8750_LOUT1V
,
reg
|
0x0100
);
reg
=
wm8750_read_reg_cache
(
codec
,
WM8750_ROUT1V
);
wm8750
_write
(
codec
,
WM8750_ROUT1V
,
reg
|
0x0100
);
reg
=
wm8750_read_reg_cache
(
codec
,
WM8750_LOUT2V
);
wm8750
_write
(
codec
,
WM8750_LOUT2V
,
reg
|
0x0100
);
reg
=
wm8750_read_reg_cache
(
codec
,
WM8750_ROUT2V
);
wm8750
_write
(
codec
,
WM8750_ROUT2V
,
reg
|
0x0100
);
reg
=
wm8750_read_reg_cache
(
codec
,
WM8750_LINVOL
);
wm8750
_write
(
codec
,
WM8750_LINVOL
,
reg
|
0x0100
);
reg
=
wm8750_read_reg_cache
(
codec
,
WM8750_RINVOL
);
wm8750
_write
(
codec
,
WM8750_RINVOL
,
reg
|
0x0100
);
reg
=
snd_soc_read
(
codec
,
WM8750_LDAC
);
snd_soc
_write
(
codec
,
WM8750_LDAC
,
reg
|
0x0100
);
reg
=
snd_soc_read
(
codec
,
WM8750_RDAC
);
snd_soc
_write
(
codec
,
WM8750_RDAC
,
reg
|
0x0100
);
reg
=
snd_soc_read
(
codec
,
WM8750_LOUT1V
);
snd_soc
_write
(
codec
,
WM8750_LOUT1V
,
reg
|
0x0100
);
reg
=
snd_soc_read
(
codec
,
WM8750_ROUT1V
);
snd_soc
_write
(
codec
,
WM8750_ROUT1V
,
reg
|
0x0100
);
reg
=
snd_soc_read
(
codec
,
WM8750_LOUT2V
);
snd_soc
_write
(
codec
,
WM8750_LOUT2V
,
reg
|
0x0100
);
reg
=
snd_soc_read
(
codec
,
WM8750_ROUT2V
);
snd_soc
_write
(
codec
,
WM8750_ROUT2V
,
reg
|
0x0100
);
reg
=
snd_soc_read
(
codec
,
WM8750_LINVOL
);
snd_soc
_write
(
codec
,
WM8750_LINVOL
,
reg
|
0x0100
);
reg
=
snd_soc_read
(
codec
,
WM8750_RINVOL
);
snd_soc
_write
(
codec
,
WM8750_RINVOL
,
reg
|
0x0100
);
snd_soc_add_controls
(
codec
,
wm8750_snd_controls
,
ARRAY_SIZE
(
wm8750_snd_controls
));
...
...
@@ -816,7 +782,7 @@ static int wm8750_init(struct snd_soc_device *socdev)
card_err:
snd_soc_free_pcms
(
socdev
);
snd_soc_dapm_free
(
socdev
);
pcm_
err:
err:
kfree
(
codec
->
reg_cache
);
return
ret
;
}
...
...
@@ -844,7 +810,7 @@ static int wm8750_i2c_probe(struct i2c_client *i2c,
i2c_set_clientdata
(
i2c
,
codec
);
codec
->
control_data
=
i2c
;
ret
=
wm8750_init
(
socdev
);
ret
=
wm8750_init
(
socdev
,
SND_SOC_I2C
);
if
(
ret
<
0
)
pr_err
(
"failed to initialise WM8750
\n
"
);
...
...
@@ -924,7 +890,7 @@ static int __devinit wm8750_spi_probe(struct spi_device *spi)
codec
->
control_data
=
spi
;
ret
=
wm8750_init
(
socdev
);
ret
=
wm8750_init
(
socdev
,
SND_SOC_SPI
);
if
(
ret
<
0
)
dev_err
(
&
spi
->
dev
,
"failed to initialise WM8750
\n
"
);
...
...
@@ -945,30 +911,6 @@ static struct spi_driver wm8750_spi_driver = {
.
probe
=
wm8750_spi_probe
,
.
remove
=
__devexit_p
(
wm8750_spi_remove
),
};
static
int
wm8750_spi_write
(
struct
spi_device
*
spi
,
const
char
*
data
,
int
len
)
{
struct
spi_transfer
t
;
struct
spi_message
m
;
u8
msg
[
2
];
if
(
len
<=
0
)
return
0
;
msg
[
0
]
=
data
[
0
];
msg
[
1
]
=
data
[
1
];
spi_message_init
(
&
m
);
memset
(
&
t
,
0
,
(
sizeof
t
));
t
.
tx_buf
=
&
msg
[
0
];
t
.
len
=
len
;
spi_message_add_tail
(
&
t
,
&
m
);
spi_sync
(
spi
,
&
m
);
return
len
;
}
#endif
static
int
wm8750_probe
(
struct
platform_device
*
pdev
)
...
...
@@ -1002,13 +944,11 @@ static int wm8750_probe(struct platform_device *pdev)
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
if
(
setup
->
i2c_address
)
{
codec
->
hw_write
=
(
hw_write_t
)
i2c_master_send
;
ret
=
wm8750_add_i2c_device
(
pdev
,
setup
);
}
#endif
#if defined(CONFIG_SPI_MASTER)
if
(
setup
->
spi
)
{
codec
->
hw_write
=
(
hw_write_t
)
wm8750_spi_write
;
ret
=
spi_register_driver
(
&
wm8750_spi_driver
);
if
(
ret
!=
0
)
printk
(
KERN_ERR
"can't add spi driver"
);
...
...
sound/soc/codecs/wm8900.c
View file @
06cddefc
...
...
@@ -183,111 +183,20 @@ static const u16 wm8900_reg_defaults[WM8900_MAXREG] = {
/* Remaining registers all zero */
};
/*
* read wm8900 register cache
*/
static
inline
unsigned
int
wm8900_read_reg_cache
(
struct
snd_soc_codec
*
codec
,
unsigned
int
reg
)
{
u16
*
cache
=
codec
->
reg_cache
;
BUG_ON
(
reg
>=
WM8900_MAXREG
);
if
(
reg
==
WM8900_REG_ID
)
return
0
;
return
cache
[
reg
];
}
/*
* write wm8900 register cache
*/
static
inline
void
wm8900_write_reg_cache
(
struct
snd_soc_codec
*
codec
,
u16
reg
,
unsigned
int
value
)
{
u16
*
cache
=
codec
->
reg_cache
;
BUG_ON
(
reg
>=
WM8900_MAXREG
);
cache
[
reg
]
=
value
;
}
/*
* write to the WM8900 register space
*/
static
int
wm8900_write
(
struct
snd_soc_codec
*
codec
,
unsigned
int
reg
,
unsigned
int
value
)
{
u8
data
[
3
];
if
(
value
==
wm8900_read_reg_cache
(
codec
,
reg
))
return
0
;
/* data is
* D15..D9 WM8900 register offset
* D8...D0 register data
*/
data
[
0
]
=
reg
;
data
[
1
]
=
value
>>
8
;
data
[
2
]
=
value
&
0x00ff
;
wm8900_write_reg_cache
(
codec
,
reg
,
value
);
if
(
codec
->
hw_write
(
codec
->
control_data
,
data
,
3
)
==
3
)
return
0
;
else
return
-
EIO
;
}
/*
* Read from the wm8900.
*/
static
unsigned
int
wm8900_chip_read
(
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
!=
WM8900_REG_ID
&&
reg
!=
WM8900_REG_POWER1
);
/* 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
)
{
printk
(
KERN_CRIT
"i2c_transfer returned %d
\n
"
,
ret
);
return
0
;
}
return
(
data
>>
8
)
|
((
data
&
0xff
)
<<
8
);
}
/*
* Read from the WM8900 register space. Most registers can't be read
* and are therefore supplied from cache.
*/
static
unsigned
int
wm8900_read
(
struct
snd_soc_codec
*
codec
,
unsigned
int
reg
)
static
int
wm8900_volatile_register
(
unsigned
int
reg
)
{
switch
(
reg
)
{
case
WM8900_REG_ID
:
return
wm8900_chip_read
(
codec
,
reg
);
case
WM8900_REG_POWER1
:
return
1
;
default:
return
wm8900_read_reg_cache
(
codec
,
reg
)
;
return
0
;
}
}
static
void
wm8900_reset
(
struct
snd_soc_codec
*
codec
)
{
wm8900
_write
(
codec
,
WM8900_REG_RESET
,
0
);
snd_soc
_write
(
codec
,
WM8900_REG_RESET
,
0
);
memcpy
(
codec
->
reg_cache
,
wm8900_reg_defaults
,
sizeof
(
codec
->
reg_cache
));
...
...
@@ -297,14 +206,14 @@ static int wm8900_hp_event(struct snd_soc_dapm_widget *w,
struct
snd_kcontrol
*
kcontrol
,
int
event
)
{
struct
snd_soc_codec
*
codec
=
w
->
codec
;
u16
hpctl1
=
wm8900
_read
(
codec
,
WM8900_REG_HPCTL1
);
u16
hpctl1
=
snd_soc
_read
(
codec
,
WM8900_REG_HPCTL1
);
switch
(
event
)
{
case
SND_SOC_DAPM_PRE_PMU
:
/* Clamp headphone outputs */
hpctl1
=
WM8900_REG_HPCTL1_HP_CLAMP_IP
|
WM8900_REG_HPCTL1_HP_CLAMP_OP
;
wm8900
_write
(
codec
,
WM8900_REG_HPCTL1
,
hpctl1
);
snd_soc
_write
(
codec
,
WM8900_REG_HPCTL1
,
hpctl1
);
break
;
case
SND_SOC_DAPM_POST_PMU
:
...
...
@@ -313,41 +222,41 @@ static int wm8900_hp_event(struct snd_soc_dapm_widget *w,
hpctl1
|=
WM8900_REG_HPCTL1_HP_SHORT
|
WM8900_REG_HPCTL1_HP_SHORT2
|
WM8900_REG_HPCTL1_HP_IPSTAGE_ENA
;
wm8900
_write
(
codec
,
WM8900_REG_HPCTL1
,
hpctl1
);
snd_soc
_write
(
codec
,
WM8900_REG_HPCTL1
,
hpctl1
);
msleep
(
400
);
/* Enable the output stage */
hpctl1
&=
~
WM8900_REG_HPCTL1_HP_CLAMP_OP
;
hpctl1
|=
WM8900_REG_HPCTL1_HP_OPSTAGE_ENA
;
wm8900
_write
(
codec
,
WM8900_REG_HPCTL1
,
hpctl1
);
snd_soc
_write
(
codec
,
WM8900_REG_HPCTL1
,
hpctl1
);
/* Remove the shorts */
hpctl1
&=
~
WM8900_REG_HPCTL1_HP_SHORT2
;
wm8900
_write
(
codec
,
WM8900_REG_HPCTL1
,
hpctl1
);
snd_soc
_write
(
codec
,
WM8900_REG_HPCTL1
,
hpctl1
);
hpctl1
&=
~
WM8900_REG_HPCTL1_HP_SHORT
;
wm8900
_write
(
codec
,
WM8900_REG_HPCTL1
,
hpctl1
);
snd_soc
_write
(
codec
,
WM8900_REG_HPCTL1
,
hpctl1
);
break
;
case
SND_SOC_DAPM_PRE_PMD
:
/* Short the output */
hpctl1
|=
WM8900_REG_HPCTL1_HP_SHORT
;
wm8900
_write
(
codec
,
WM8900_REG_HPCTL1
,
hpctl1
);
snd_soc
_write
(
codec
,
WM8900_REG_HPCTL1
,
hpctl1
);
/* Disable the output stage */
hpctl1
&=
~
WM8900_REG_HPCTL1_HP_OPSTAGE_ENA
;
wm8900
_write
(
codec
,
WM8900_REG_HPCTL1
,
hpctl1
);
snd_soc
_write
(
codec
,
WM8900_REG_HPCTL1
,
hpctl1
);
/* Clamp the outputs and power down input */
hpctl1
|=
WM8900_REG_HPCTL1_HP_CLAMP_IP
|
WM8900_REG_HPCTL1_HP_CLAMP_OP
;
hpctl1
&=
~
WM8900_REG_HPCTL1_HP_IPSTAGE_ENA
;
wm8900
_write
(
codec
,
WM8900_REG_HPCTL1
,
hpctl1
);
snd_soc
_write
(
codec
,
WM8900_REG_HPCTL1
,
hpctl1
);
break
;
case
SND_SOC_DAPM_POST_PMD
:
/* Disable everything */
wm8900
_write
(
codec
,
WM8900_REG_HPCTL1
,
0
);
snd_soc
_write
(
codec
,
WM8900_REG_HPCTL1
,
0
);
break
;
default:
...
...
@@ -723,7 +632,7 @@ static int wm8900_hw_params(struct snd_pcm_substream *substream,
struct
snd_soc_codec
*
codec
=
socdev
->
card
->
codec
;
u16
reg
;
reg
=
wm8900
_read
(
codec
,
WM8900_REG_AUDIO1
)
&
~
0x60
;
reg
=
snd_soc
_read
(
codec
,
WM8900_REG_AUDIO1
)
&
~
0x60
;
switch
(
params_format
(
params
))
{
case
SNDRV_PCM_FORMAT_S16_LE
:
...
...
@@ -741,17 +650,17 @@ static int wm8900_hw_params(struct snd_pcm_substream *substream,
return
-
EINVAL
;
}
wm8900
_write
(
codec
,
WM8900_REG_AUDIO1
,
reg
);
snd_soc
_write
(
codec
,
WM8900_REG_AUDIO1
,
reg
);
if
(
substream
->
stream
==
SNDRV_PCM_STREAM_PLAYBACK
)
{
reg
=
wm8900
_read
(
codec
,
WM8900_REG_DACCTRL
);
reg
=
snd_soc
_read
(
codec
,
WM8900_REG_DACCTRL
);
if
(
params_rate
(
params
)
<=
24000
)
reg
|=
WM8900_REG_DACCTRL_DAC_SB_FILT
;
else
reg
&=
~
WM8900_REG_DACCTRL_DAC_SB_FILT
;
wm8900
_write
(
codec
,
WM8900_REG_DACCTRL
,
reg
);
snd_soc
_write
(
codec
,
WM8900_REG_DACCTRL
,
reg
);
}
return
0
;
...
...
@@ -845,18 +754,18 @@ static int wm8900_set_fll(struct snd_soc_codec *codec,
return
0
;
/* The digital side should be disabled during any change. */
reg
=
wm8900
_read
(
codec
,
WM8900_REG_POWER1
);
wm8900
_write
(
codec
,
WM8900_REG_POWER1
,
reg
=
snd_soc
_read
(
codec
,
WM8900_REG_POWER1
);
snd_soc
_write
(
codec
,
WM8900_REG_POWER1
,
reg
&
(
~
WM8900_REG_POWER1_FLL_ENA
));
/* Disable the FLL? */
if
(
!
freq_in
||
!
freq_out
)
{
reg
=
wm8900
_read
(
codec
,
WM8900_REG_CLOCKING1
);
wm8900
_write
(
codec
,
WM8900_REG_CLOCKING1
,
reg
=
snd_soc
_read
(
codec
,
WM8900_REG_CLOCKING1
);
snd_soc
_write
(
codec
,
WM8900_REG_CLOCKING1
,
reg
&
(
~
WM8900_REG_CLOCKING1_MCLK_SRC
));
reg
=
wm8900
_read
(
codec
,
WM8900_REG_FLLCTL1
);
wm8900
_write
(
codec
,
WM8900_REG_FLLCTL1
,
reg
=
snd_soc
_read
(
codec
,
WM8900_REG_FLLCTL1
);
snd_soc
_write
(
codec
,
WM8900_REG_FLLCTL1
,
reg
&
(
~
WM8900_REG_FLLCTL1_OSC_ENA
));
wm8900
->
fll_in
=
freq_in
;
...
...
@@ -873,33 +782,33 @@ static int wm8900_set_fll(struct snd_soc_codec *codec,
/* The osclilator *MUST* be enabled before we enable the
* digital circuit. */
wm8900
_write
(
codec
,
WM8900_REG_FLLCTL1
,
snd_soc
_write
(
codec
,
WM8900_REG_FLLCTL1
,
fll_div
.
fll_ratio
|
WM8900_REG_FLLCTL1_OSC_ENA
);
wm8900
_write
(
codec
,
WM8900_REG_FLLCTL4
,
fll_div
.
n
>>
5
);
wm8900
_write
(
codec
,
WM8900_REG_FLLCTL5
,
snd_soc
_write
(
codec
,
WM8900_REG_FLLCTL4
,
fll_div
.
n
>>
5
);
snd_soc
_write
(
codec
,
WM8900_REG_FLLCTL5
,
(
fll_div
.
fllclk_div
<<
6
)
|
(
fll_div
.
n
&
0x1f
));
if
(
fll_div
.
k
)
{
wm8900
_write
(
codec
,
WM8900_REG_FLLCTL2
,
snd_soc
_write
(
codec
,
WM8900_REG_FLLCTL2
,
(
fll_div
.
k
>>
8
)
|
0x100
);
wm8900
_write
(
codec
,
WM8900_REG_FLLCTL3
,
fll_div
.
k
&
0xff
);
snd_soc
_write
(
codec
,
WM8900_REG_FLLCTL3
,
fll_div
.
k
&
0xff
);
}
else
wm8900
_write
(
codec
,
WM8900_REG_FLLCTL2
,
0
);
snd_soc
_write
(
codec
,
WM8900_REG_FLLCTL2
,
0
);
if
(
fll_div
.
fll_slow_lock_ref
)
wm8900
_write
(
codec
,
WM8900_REG_FLLCTL6
,
snd_soc
_write
(
codec
,
WM8900_REG_FLLCTL6
,
WM8900_REG_FLLCTL6_FLL_SLOW_LOCK_REF
);
else
wm8900
_write
(
codec
,
WM8900_REG_FLLCTL6
,
0
);
snd_soc
_write
(
codec
,
WM8900_REG_FLLCTL6
,
0
);
reg
=
wm8900
_read
(
codec
,
WM8900_REG_POWER1
);
wm8900
_write
(
codec
,
WM8900_REG_POWER1
,
reg
=
snd_soc
_read
(
codec
,
WM8900_REG_POWER1
);
snd_soc
_write
(
codec
,
WM8900_REG_POWER1
,
reg
|
WM8900_REG_POWER1_FLL_ENA
);
reenable:
reg
=
wm8900
_read
(
codec
,
WM8900_REG_CLOCKING1
);
wm8900
_write
(
codec
,
WM8900_REG_CLOCKING1
,
reg
=
snd_soc
_read
(
codec
,
WM8900_REG_CLOCKING1
);
snd_soc
_write
(
codec
,
WM8900_REG_CLOCKING1
,
reg
|
WM8900_REG_CLOCKING1_MCLK_SRC
);
return
0
;
...
...
@@ -919,38 +828,38 @@ static int wm8900_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
switch
(
div_id
)
{
case
WM8900_BCLK_DIV
:
reg
=
wm8900
_read
(
codec
,
WM8900_REG_CLOCKING1
);
wm8900
_write
(
codec
,
WM8900_REG_CLOCKING1
,
reg
=
snd_soc
_read
(
codec
,
WM8900_REG_CLOCKING1
);
snd_soc
_write
(
codec
,
WM8900_REG_CLOCKING1
,
div
|
(
reg
&
WM8900_REG_CLOCKING1_BCLK_MASK
));
break
;
case
WM8900_OPCLK_DIV
:
reg
=
wm8900
_read
(
codec
,
WM8900_REG_CLOCKING1
);
wm8900
_write
(
codec
,
WM8900_REG_CLOCKING1
,
reg
=
snd_soc
_read
(
codec
,
WM8900_REG_CLOCKING1
);
snd_soc
_write
(
codec
,
WM8900_REG_CLOCKING1
,
div
|
(
reg
&
WM8900_REG_CLOCKING1_OPCLK_MASK
));
break
;
case
WM8900_DAC_LRCLK
:
reg
=
wm8900
_read
(
codec
,
WM8900_REG_AUDIO4
);
wm8900
_write
(
codec
,
WM8900_REG_AUDIO4
,
reg
=
snd_soc
_read
(
codec
,
WM8900_REG_AUDIO4
);
snd_soc
_write
(
codec
,
WM8900_REG_AUDIO4
,
div
|
(
reg
&
WM8900_LRC_MASK
));
break
;
case
WM8900_ADC_LRCLK
:
reg
=
wm8900
_read
(
codec
,
WM8900_REG_AUDIO3
);
wm8900
_write
(
codec
,
WM8900_REG_AUDIO3
,
reg
=
snd_soc
_read
(
codec
,
WM8900_REG_AUDIO3
);
snd_soc
_write
(
codec
,
WM8900_REG_AUDIO3
,
div
|
(
reg
&
WM8900_LRC_MASK
));
break
;
case
WM8900_DAC_CLKDIV
:
reg
=
wm8900
_read
(
codec
,
WM8900_REG_CLOCKING2
);
wm8900
_write
(
codec
,
WM8900_REG_CLOCKING2
,
reg
=
snd_soc
_read
(
codec
,
WM8900_REG_CLOCKING2
);
snd_soc
_write
(
codec
,
WM8900_REG_CLOCKING2
,
div
|
(
reg
&
WM8900_REG_CLOCKING2_DAC_CLKDIV
));
break
;
case
WM8900_ADC_CLKDIV
:
reg
=
wm8900
_read
(
codec
,
WM8900_REG_CLOCKING2
);
wm8900
_write
(
codec
,
WM8900_REG_CLOCKING2
,
reg
=
snd_soc
_read
(
codec
,
WM8900_REG_CLOCKING2
);
snd_soc
_write
(
codec
,
WM8900_REG_CLOCKING2
,
div
|
(
reg
&
WM8900_REG_CLOCKING2_ADC_CLKDIV
));
break
;
case
WM8900_LRCLK_MODE
:
reg
=
wm8900
_read
(
codec
,
WM8900_REG_DACCTRL
);
wm8900
_write
(
codec
,
WM8900_REG_DACCTRL
,
reg
=
snd_soc
_read
(
codec
,
WM8900_REG_DACCTRL
);
snd_soc
_write
(
codec
,
WM8900_REG_DACCTRL
,
div
|
(
reg
&
WM8900_REG_DACCTRL_AIF_LRCLKRATE
));
break
;
default:
...
...
@@ -967,10 +876,10 @@ static int wm8900_set_dai_fmt(struct snd_soc_dai *codec_dai,
struct
snd_soc_codec
*
codec
=
codec_dai
->
codec
;
unsigned
int
clocking1
,
aif1
,
aif3
,
aif4
;
clocking1
=
wm8900
_read
(
codec
,
WM8900_REG_CLOCKING1
);
aif1
=
wm8900
_read
(
codec
,
WM8900_REG_AUDIO1
);
aif3
=
wm8900
_read
(
codec
,
WM8900_REG_AUDIO3
);
aif4
=
wm8900
_read
(
codec
,
WM8900_REG_AUDIO4
);
clocking1
=
snd_soc
_read
(
codec
,
WM8900_REG_CLOCKING1
);
aif1
=
snd_soc
_read
(
codec
,
WM8900_REG_AUDIO1
);
aif3
=
snd_soc
_read
(
codec
,
WM8900_REG_AUDIO3
);
aif4
=
snd_soc
_read
(
codec
,
WM8900_REG_AUDIO4
);
/* set master/slave audio interface */
switch
(
fmt
&
SND_SOC_DAIFMT_MASTER_MASK
)
{
...
...
@@ -1066,10 +975,10 @@ static int wm8900_set_dai_fmt(struct snd_soc_dai *codec_dai,
return
-
EINVAL
;
}
wm8900
_write
(
codec
,
WM8900_REG_CLOCKING1
,
clocking1
);
wm8900
_write
(
codec
,
WM8900_REG_AUDIO1
,
aif1
);
wm8900
_write
(
codec
,
WM8900_REG_AUDIO3
,
aif3
);
wm8900
_write
(
codec
,
WM8900_REG_AUDIO4
,
aif4
);
snd_soc
_write
(
codec
,
WM8900_REG_CLOCKING1
,
clocking1
);
snd_soc
_write
(
codec
,
WM8900_REG_AUDIO1
,
aif1
);
snd_soc
_write
(
codec
,
WM8900_REG_AUDIO3
,
aif3
);
snd_soc
_write
(
codec
,
WM8900_REG_AUDIO4
,
aif4
);
return
0
;
}
...
...
@@ -1079,14 +988,14 @@ static int wm8900_digital_mute(struct snd_soc_dai *codec_dai, int mute)
struct
snd_soc_codec
*
codec
=
codec_dai
->
codec
;
u16
reg
;
reg
=
wm8900
_read
(
codec
,
WM8900_REG_DACCTRL
);
reg
=
snd_soc
_read
(
codec
,
WM8900_REG_DACCTRL
);
if
(
mute
)
reg
|=
WM8900_REG_DACCTRL_MUTE
;
else
reg
&=
~
WM8900_REG_DACCTRL_MUTE
;
wm8900
_write
(
codec
,
WM8900_REG_DACCTRL
,
reg
);
snd_soc
_write
(
codec
,
WM8900_REG_DACCTRL
,
reg
);
return
0
;
}
...
...
@@ -1135,11 +1044,11 @@ static int wm8900_set_bias_level(struct snd_soc_codec *codec,
switch
(
level
)
{
case
SND_SOC_BIAS_ON
:
/* Enable thermal shutdown */
reg
=
wm8900
_read
(
codec
,
WM8900_REG_GPIO
);
wm8900
_write
(
codec
,
WM8900_REG_GPIO
,
reg
=
snd_soc
_read
(
codec
,
WM8900_REG_GPIO
);
snd_soc
_write
(
codec
,
WM8900_REG_GPIO
,
reg
|
WM8900_REG_GPIO_TEMP_ENA
);
reg
=
wm8900
_read
(
codec
,
WM8900_REG_ADDCTL
);
wm8900
_write
(
codec
,
WM8900_REG_ADDCTL
,
reg
=
snd_soc
_read
(
codec
,
WM8900_REG_ADDCTL
);
snd_soc
_write
(
codec
,
WM8900_REG_ADDCTL
,
reg
|
WM8900_REG_ADDCTL_TEMP_SD
);
break
;
...
...
@@ -1150,69 +1059,69 @@ static int wm8900_set_bias_level(struct snd_soc_codec *codec,
/* Charge capacitors if initial power up */
if
(
codec
->
bias_level
==
SND_SOC_BIAS_OFF
)
{
/* STARTUP_BIAS_ENA on */
wm8900
_write
(
codec
,
WM8900_REG_POWER1
,
snd_soc
_write
(
codec
,
WM8900_REG_POWER1
,
WM8900_REG_POWER1_STARTUP_BIAS_ENA
);
/* Startup bias mode */
wm8900
_write
(
codec
,
WM8900_REG_ADDCTL
,
snd_soc
_write
(
codec
,
WM8900_REG_ADDCTL
,
WM8900_REG_ADDCTL_BIAS_SRC
|
WM8900_REG_ADDCTL_VMID_SOFTST
);
/* VMID 2x50k */
wm8900
_write
(
codec
,
WM8900_REG_POWER1
,
snd_soc
_write
(
codec
,
WM8900_REG_POWER1
,
WM8900_REG_POWER1_STARTUP_BIAS_ENA
|
0x1
);
/* Allow capacitors to charge */
schedule_timeout_interruptible
(
msecs_to_jiffies
(
400
));
/* Enable bias */
wm8900
_write
(
codec
,
WM8900_REG_POWER1
,
snd_soc
_write
(
codec
,
WM8900_REG_POWER1
,
WM8900_REG_POWER1_STARTUP_BIAS_ENA
|
WM8900_REG_POWER1_BIAS_ENA
|
0x1
);
wm8900
_write
(
codec
,
WM8900_REG_ADDCTL
,
0
);
snd_soc
_write
(
codec
,
WM8900_REG_ADDCTL
,
0
);
wm8900
_write
(
codec
,
WM8900_REG_POWER1
,
snd_soc
_write
(
codec
,
WM8900_REG_POWER1
,
WM8900_REG_POWER1_BIAS_ENA
|
0x1
);
}
reg
=
wm8900
_read
(
codec
,
WM8900_REG_POWER1
);
wm8900
_write
(
codec
,
WM8900_REG_POWER1
,
reg
=
snd_soc
_read
(
codec
,
WM8900_REG_POWER1
);
snd_soc
_write
(
codec
,
WM8900_REG_POWER1
,
(
reg
&
WM8900_REG_POWER1_FLL_ENA
)
|
WM8900_REG_POWER1_BIAS_ENA
|
0x1
);
wm8900
_write
(
codec
,
WM8900_REG_POWER2
,
snd_soc
_write
(
codec
,
WM8900_REG_POWER2
,
WM8900_REG_POWER2_SYSCLK_ENA
);
wm8900
_write
(
codec
,
WM8900_REG_POWER3
,
0
);
snd_soc
_write
(
codec
,
WM8900_REG_POWER3
,
0
);
break
;
case
SND_SOC_BIAS_OFF
:
/* Startup bias enable */
reg
=
wm8900
_read
(
codec
,
WM8900_REG_POWER1
);
wm8900
_write
(
codec
,
WM8900_REG_POWER1
,
reg
=
snd_soc
_read
(
codec
,
WM8900_REG_POWER1
);
snd_soc
_write
(
codec
,
WM8900_REG_POWER1
,
reg
&
WM8900_REG_POWER1_STARTUP_BIAS_ENA
);
wm8900
_write
(
codec
,
WM8900_REG_ADDCTL
,
snd_soc
_write
(
codec
,
WM8900_REG_ADDCTL
,
WM8900_REG_ADDCTL_BIAS_SRC
|
WM8900_REG_ADDCTL_VMID_SOFTST
);
/* Discharge caps */
wm8900
_write
(
codec
,
WM8900_REG_POWER1
,
snd_soc
_write
(
codec
,
WM8900_REG_POWER1
,
WM8900_REG_POWER1_STARTUP_BIAS_ENA
);
schedule_timeout_interruptible
(
msecs_to_jiffies
(
500
));
/* Remove clamp */
wm8900
_write
(
codec
,
WM8900_REG_HPCTL1
,
0
);
snd_soc
_write
(
codec
,
WM8900_REG_HPCTL1
,
0
);
/* Power down */
wm8900
_write
(
codec
,
WM8900_REG_ADDCTL
,
0
);
wm8900
_write
(
codec
,
WM8900_REG_POWER1
,
0
);
wm8900
_write
(
codec
,
WM8900_REG_POWER2
,
0
);
wm8900
_write
(
codec
,
WM8900_REG_POWER3
,
0
);
snd_soc
_write
(
codec
,
WM8900_REG_ADDCTL
,
0
);
snd_soc
_write
(
codec
,
WM8900_REG_POWER1
,
0
);
snd_soc
_write
(
codec
,
WM8900_REG_POWER2
,
0
);
snd_soc
_write
(
codec
,
WM8900_REG_POWER3
,
0
);
/* Need to let things settle before stopping the clock
* to ensure that restart works, see "Stopping the
* master clock" in the datasheet. */
schedule_timeout_interruptible
(
msecs_to_jiffies
(
1
));
wm8900
_write
(
codec
,
WM8900_REG_POWER2
,
snd_soc
_write
(
codec
,
WM8900_REG_POWER2
,
WM8900_REG_POWER2_SYSCLK_ENA
);
break
;
}
...
...
@@ -1275,7 +1184,7 @@ static int wm8900_resume(struct platform_device *pdev)
if
(
cache
)
{
for
(
i
=
0
;
i
<
WM8900_MAXREG
;
i
++
)
wm8900
_write
(
codec
,
i
,
cache
[
i
]);
snd_soc
_write
(
codec
,
i
,
cache
[
i
]);
kfree
(
cache
);
}
else
dev_err
(
&
pdev
->
dev
,
"Unable to allocate register cache
\n
"
);
...
...
@@ -1308,16 +1217,20 @@ static __devinit int wm8900_i2c_probe(struct i2c_client *i2c,
codec
->
name
=
"WM8900"
;
codec
->
owner
=
THIS_MODULE
;
codec
->
read
=
wm8900_read
;
codec
->
write
=
wm8900_write
;
codec
->
dai
=
&
wm8900_dai
;
codec
->
num_dai
=
1
;
codec
->
hw_write
=
(
hw_write_t
)
i2c_master_send
;
codec
->
control_data
=
i2c
;
codec
->
set_bias_level
=
wm8900_set_bias_level
;
codec
->
volatile_register
=
wm8900_volatile_register
;
codec
->
dev
=
&
i2c
->
dev
;
reg
=
wm8900_read
(
codec
,
WM8900_REG_ID
);
ret
=
snd_soc_codec_set_cache_io
(
codec
,
8
,
16
,
SND_SOC_I2C
);
if
(
ret
!=
0
)
{
dev_err
(
&
i2c
->
dev
,
"Failed to set cache I/O: %d
\n
"
,
ret
);
goto
err
;
}
reg
=
snd_soc_read
(
codec
,
WM8900_REG_ID
);
if
(
reg
!=
0x8900
)
{
dev_err
(
&
i2c
->
dev
,
"Device is not a WM8900 - ID %x
\n
"
,
reg
);
ret
=
-
ENODEV
;
...
...
@@ -1325,7 +1238,7 @@ static __devinit int wm8900_i2c_probe(struct i2c_client *i2c,
}
/* Read back from the chip */
reg
=
wm8900_chip
_read
(
codec
,
WM8900_REG_POWER1
);
reg
=
snd_soc
_read
(
codec
,
WM8900_REG_POWER1
);
reg
=
(
reg
>>
12
)
&
0xf
;
dev_info
(
&
i2c
->
dev
,
"WM8900 revision %d
\n
"
,
reg
);
...
...
@@ -1335,29 +1248,29 @@ static __devinit int wm8900_i2c_probe(struct i2c_client *i2c,
wm8900_set_bias_level
(
codec
,
SND_SOC_BIAS_STANDBY
);
/* Latch the volume update bits */
wm8900
_write
(
codec
,
WM8900_REG_LINVOL
,
wm8900
_read
(
codec
,
WM8900_REG_LINVOL
)
|
0x100
);
wm8900
_write
(
codec
,
WM8900_REG_RINVOL
,
wm8900
_read
(
codec
,
WM8900_REG_RINVOL
)
|
0x100
);
wm8900
_write
(
codec
,
WM8900_REG_LOUT1CTL
,
wm8900
_read
(
codec
,
WM8900_REG_LOUT1CTL
)
|
0x100
);
wm8900
_write
(
codec
,
WM8900_REG_ROUT1CTL
,
wm8900
_read
(
codec
,
WM8900_REG_ROUT1CTL
)
|
0x100
);
wm8900
_write
(
codec
,
WM8900_REG_LOUT2CTL
,
wm8900
_read
(
codec
,
WM8900_REG_LOUT2CTL
)
|
0x100
);
wm8900
_write
(
codec
,
WM8900_REG_ROUT2CTL
,
wm8900
_read
(
codec
,
WM8900_REG_ROUT2CTL
)
|
0x100
);
wm8900
_write
(
codec
,
WM8900_REG_LDAC_DV
,
wm8900
_read
(
codec
,
WM8900_REG_LDAC_DV
)
|
0x100
);
wm8900
_write
(
codec
,
WM8900_REG_RDAC_DV
,
wm8900
_read
(
codec
,
WM8900_REG_RDAC_DV
)
|
0x100
);
wm8900
_write
(
codec
,
WM8900_REG_LADC_DV
,
wm8900
_read
(
codec
,
WM8900_REG_LADC_DV
)
|
0x100
);
wm8900
_write
(
codec
,
WM8900_REG_RADC_DV
,
wm8900
_read
(
codec
,
WM8900_REG_RADC_DV
)
|
0x100
);
snd_soc
_write
(
codec
,
WM8900_REG_LINVOL
,
snd_soc
_read
(
codec
,
WM8900_REG_LINVOL
)
|
0x100
);
snd_soc
_write
(
codec
,
WM8900_REG_RINVOL
,
snd_soc
_read
(
codec
,
WM8900_REG_RINVOL
)
|
0x100
);
snd_soc
_write
(
codec
,
WM8900_REG_LOUT1CTL
,
snd_soc
_read
(
codec
,
WM8900_REG_LOUT1CTL
)
|
0x100
);
snd_soc
_write
(
codec
,
WM8900_REG_ROUT1CTL
,
snd_soc
_read
(
codec
,
WM8900_REG_ROUT1CTL
)
|
0x100
);
snd_soc
_write
(
codec
,
WM8900_REG_LOUT2CTL
,
snd_soc
_read
(
codec
,
WM8900_REG_LOUT2CTL
)
|
0x100
);
snd_soc
_write
(
codec
,
WM8900_REG_ROUT2CTL
,
snd_soc
_read
(
codec
,
WM8900_REG_ROUT2CTL
)
|
0x100
);
snd_soc
_write
(
codec
,
WM8900_REG_LDAC_DV
,
snd_soc
_read
(
codec
,
WM8900_REG_LDAC_DV
)
|
0x100
);
snd_soc
_write
(
codec
,
WM8900_REG_RDAC_DV
,
snd_soc
_read
(
codec
,
WM8900_REG_RDAC_DV
)
|
0x100
);
snd_soc
_write
(
codec
,
WM8900_REG_LADC_DV
,
snd_soc
_read
(
codec
,
WM8900_REG_LADC_DV
)
|
0x100
);
snd_soc
_write
(
codec
,
WM8900_REG_RADC_DV
,
snd_soc
_read
(
codec
,
WM8900_REG_RADC_DV
)
|
0x100
);
/* Set the DAC and mixer output bias */
wm8900
_write
(
codec
,
WM8900_REG_OUTBIASCTL
,
0x81
);
snd_soc
_write
(
codec
,
WM8900_REG_OUTBIASCTL
,
0x81
);
wm8900_dai
.
dev
=
&
i2c
->
dev
;
...
...
sound/soc/codecs/wm8903.c
View file @
06cddefc
...
...
@@ -225,94 +225,18 @@ struct wm8903_priv {
struct
snd_pcm_substream
*
slave_substream
;
};
static
unsigned
int
wm8903_read_reg_cache
(
struct
snd_soc_codec
*
codec
,
unsigned
int
reg
)
{
u16
*
cache
=
codec
->
reg_cache
;
BUG_ON
(
reg
>=
ARRAY_SIZE
(
wm8903_reg_defaults
));
return
cache
[
reg
];
}
static
unsigned
int
wm8903_hw_read
(
struct
snd_soc_codec
*
codec
,
u8
reg
)
{
struct
i2c_msg
xfer
[
2
];
u16
data
;
int
ret
;
struct
i2c_client
*
client
=
codec
->
control_data
;
/* 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
)
{
pr_err
(
"i2c_transfer returned %d
\n
"
,
ret
);
return
0
;
}
return
(
data
>>
8
)
|
((
data
&
0xff
)
<<
8
);
}
static
unsigned
int
wm8903_read
(
struct
snd_soc_codec
*
codec
,
unsigned
int
reg
)
static
int
wm8903_volatile_register
(
unsigned
int
reg
)
{
switch
(
reg
)
{
case
WM8903_SW_RESET_AND_ID
:
case
WM8903_REVISION_NUMBER
:
case
WM8903_INTERRUPT_STATUS_1
:
case
WM8903_WRITE_SEQUENCER_4
:
return
wm8903_hw_read
(
codec
,
reg
)
;
return
1
;
default:
return
wm8903_read_reg_cache
(
codec
,
reg
);
}
}
static
void
wm8903_write_reg_cache
(
struct
snd_soc_codec
*
codec
,
u16
reg
,
unsigned
int
value
)
{
u16
*
cache
=
codec
->
reg_cache
;
BUG_ON
(
reg
>=
ARRAY_SIZE
(
wm8903_reg_defaults
));
switch
(
reg
)
{
case
WM8903_SW_RESET_AND_ID
:
case
WM8903_REVISION_NUMBER
:
break
;
default:
cache
[
reg
]
=
value
;
break
;
}
}
static
int
wm8903_write
(
struct
snd_soc_codec
*
codec
,
unsigned
int
reg
,
unsigned
int
value
)
{
u8
data
[
3
];
wm8903_write_reg_cache
(
codec
,
reg
,
value
);
/* Data format is 1 byte of address followed by 2 bytes of data */
data
[
0
]
=
reg
;
data
[
1
]
=
(
value
>>
8
)
&
0xff
;
data
[
2
]
=
value
&
0xff
;
if
(
codec
->
hw_write
(
codec
->
control_data
,
data
,
3
)
==
2
)
return
0
;
else
return
-
EIO
;
}
}
static
int
wm8903_run_sequence
(
struct
snd_soc_codec
*
codec
,
unsigned
int
start
)
...
...
@@ -323,13 +247,13 @@ static int wm8903_run_sequence(struct snd_soc_codec *codec, unsigned int start)
BUG_ON
(
start
>
48
);
/* Enable the sequencer */
reg
[
0
]
=
wm8903
_read
(
codec
,
WM8903_WRITE_SEQUENCER_0
);
reg
[
0
]
=
snd_soc
_read
(
codec
,
WM8903_WRITE_SEQUENCER_0
);
reg
[
0
]
|=
WM8903_WSEQ_ENA
;
wm8903
_write
(
codec
,
WM8903_WRITE_SEQUENCER_0
,
reg
[
0
]);
snd_soc
_write
(
codec
,
WM8903_WRITE_SEQUENCER_0
,
reg
[
0
]);
dev_dbg
(
&
i2c
->
dev
,
"Starting sequence at %d
\n
"
,
start
);
wm8903
_write
(
codec
,
WM8903_WRITE_SEQUENCER_3
,
snd_soc
_write
(
codec
,
WM8903_WRITE_SEQUENCER_3
,
start
|
WM8903_WSEQ_START
);
/* Wait for it to complete. If we have the interrupt wired up then
...
...
@@ -339,13 +263,13 @@ static int wm8903_run_sequence(struct snd_soc_codec *codec, unsigned int start)
do
{
msleep
(
10
);
reg
[
4
]
=
wm8903
_read
(
codec
,
WM8903_WRITE_SEQUENCER_4
);
reg
[
4
]
=
snd_soc
_read
(
codec
,
WM8903_WRITE_SEQUENCER_4
);
}
while
(
reg
[
4
]
&
WM8903_WSEQ_BUSY
);
dev_dbg
(
&
i2c
->
dev
,
"Sequence complete
\n
"
);
/* Disable the sequencer again */
wm8903
_write
(
codec
,
WM8903_WRITE_SEQUENCER_0
,
snd_soc
_write
(
codec
,
WM8903_WRITE_SEQUENCER_0
,
reg
[
0
]
&
~
WM8903_WSEQ_ENA
);
return
0
;
...
...
@@ -357,12 +281,12 @@ static void wm8903_sync_reg_cache(struct snd_soc_codec *codec, u16 *cache)
/* There really ought to be something better we can do here :/ */
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
wm8903_reg_defaults
);
i
++
)
cache
[
i
]
=
wm8903_
hw_read
(
codec
,
i
);
cache
[
i
]
=
codec
->
hw_read
(
codec
,
i
);
}
static
void
wm8903_reset
(
struct
snd_soc_codec
*
codec
)
{
wm8903
_write
(
codec
,
WM8903_SW_RESET_AND_ID
,
0
);
snd_soc
_write
(
codec
,
WM8903_SW_RESET_AND_ID
,
0
);
memcpy
(
codec
->
reg_cache
,
wm8903_reg_defaults
,
sizeof
(
wm8903_reg_defaults
));
}
...
...
@@ -423,52 +347,52 @@ static int wm8903_output_event(struct snd_soc_dapm_widget *w,
}
if
(
event
&
SND_SOC_DAPM_PRE_PMU
)
{
val
=
wm8903
_read
(
codec
,
reg
);
val
=
snd_soc
_read
(
codec
,
reg
);
/* Short the output */
val
&=
~
(
WM8903_OUTPUT_SHORT
<<
shift
);
wm8903
_write
(
codec
,
reg
,
val
);
snd_soc
_write
(
codec
,
reg
,
val
);
}
if
(
event
&
SND_SOC_DAPM_POST_PMU
)
{
val
=
wm8903
_read
(
codec
,
reg
);
val
=
snd_soc
_read
(
codec
,
reg
);
val
|=
(
WM8903_OUTPUT_IN
<<
shift
);
wm8903
_write
(
codec
,
reg
,
val
);
snd_soc
_write
(
codec
,
reg
,
val
);
val
|=
(
WM8903_OUTPUT_INT
<<
shift
);
wm8903
_write
(
codec
,
reg
,
val
);
snd_soc
_write
(
codec
,
reg
,
val
);
/* Turn on the output ENA_OUTP */
val
|=
(
WM8903_OUTPUT_OUT
<<
shift
);
wm8903
_write
(
codec
,
reg
,
val
);
snd_soc
_write
(
codec
,
reg
,
val
);
/* Enable the DC servo */
dcs_reg
=
wm8903
_read
(
codec
,
WM8903_DC_SERVO_0
);
dcs_reg
=
snd_soc
_read
(
codec
,
WM8903_DC_SERVO_0
);
dcs_reg
|=
dcs_bit
;
wm8903
_write
(
codec
,
WM8903_DC_SERVO_0
,
dcs_reg
);
snd_soc
_write
(
codec
,
WM8903_DC_SERVO_0
,
dcs_reg
);
/* Remove the short */
val
|=
(
WM8903_OUTPUT_SHORT
<<
shift
);
wm8903
_write
(
codec
,
reg
,
val
);
snd_soc
_write
(
codec
,
reg
,
val
);
}
if
(
event
&
SND_SOC_DAPM_PRE_PMD
)
{
val
=
wm8903
_read
(
codec
,
reg
);
val
=
snd_soc
_read
(
codec
,
reg
);
/* Short the output */
val
&=
~
(
WM8903_OUTPUT_SHORT
<<
shift
);
wm8903
_write
(
codec
,
reg
,
val
);
snd_soc
_write
(
codec
,
reg
,
val
);
/* Disable the DC servo */
dcs_reg
=
wm8903
_read
(
codec
,
WM8903_DC_SERVO_0
);
dcs_reg
=
snd_soc
_read
(
codec
,
WM8903_DC_SERVO_0
);
dcs_reg
&=
~
dcs_bit
;
wm8903
_write
(
codec
,
WM8903_DC_SERVO_0
,
dcs_reg
);
snd_soc
_write
(
codec
,
WM8903_DC_SERVO_0
,
dcs_reg
);
/* Then disable the intermediate and output stages */
val
&=
~
((
WM8903_OUTPUT_OUT
|
WM8903_OUTPUT_INT
|
WM8903_OUTPUT_IN
)
<<
shift
);
wm8903
_write
(
codec
,
reg
,
val
);
snd_soc
_write
(
codec
,
reg
,
val
);
}
return
0
;
...
...
@@ -492,13 +416,13 @@ static int wm8903_class_w_put(struct snd_kcontrol *kcontrol,
u16
reg
;
int
ret
;
reg
=
wm8903
_read
(
codec
,
WM8903_CLASS_W_0
);
reg
=
snd_soc
_read
(
codec
,
WM8903_CLASS_W_0
);
/* Turn it off if we're about to enable bypass */
if
(
ucontrol
->
value
.
integer
.
value
[
0
])
{
if
(
wm8903
->
class_w_users
==
0
)
{
dev_dbg
(
&
i2c
->
dev
,
"Disabling Class W
\n
"
);
wm8903
_write
(
codec
,
WM8903_CLASS_W_0
,
reg
&
snd_soc
_write
(
codec
,
WM8903_CLASS_W_0
,
reg
&
~
(
WM8903_CP_DYN_FREQ
|
WM8903_CP_DYN_V
));
}
wm8903
->
class_w_users
++
;
...
...
@@ -511,7 +435,7 @@ static int wm8903_class_w_put(struct snd_kcontrol *kcontrol,
if
(
!
ucontrol
->
value
.
integer
.
value
[
0
])
{
if
(
wm8903
->
class_w_users
==
1
)
{
dev_dbg
(
&
i2c
->
dev
,
"Enabling Class W
\n
"
);
wm8903
_write
(
codec
,
WM8903_CLASS_W_0
,
reg
|
snd_soc
_write
(
codec
,
WM8903_CLASS_W_0
,
reg
|
WM8903_CP_DYN_FREQ
|
WM8903_CP_DYN_V
);
}
wm8903
->
class_w_users
--
;
...
...
@@ -1009,55 +933,55 @@ static int wm8903_set_bias_level(struct snd_soc_codec *codec,
switch
(
level
)
{
case
SND_SOC_BIAS_ON
:
case
SND_SOC_BIAS_PREPARE
:
reg
=
wm8903
_read
(
codec
,
WM8903_VMID_CONTROL_0
);
reg
=
snd_soc
_read
(
codec
,
WM8903_VMID_CONTROL_0
);
reg
&=
~
(
WM8903_VMID_RES_MASK
);
reg
|=
WM8903_VMID_RES_50K
;
wm8903
_write
(
codec
,
WM8903_VMID_CONTROL_0
,
reg
);
snd_soc
_write
(
codec
,
WM8903_VMID_CONTROL_0
,
reg
);
break
;
case
SND_SOC_BIAS_STANDBY
:
if
(
codec
->
bias_level
==
SND_SOC_BIAS_OFF
)
{
wm8903
_write
(
codec
,
WM8903_CLOCK_RATES_2
,
snd_soc
_write
(
codec
,
WM8903_CLOCK_RATES_2
,
WM8903_CLK_SYS_ENA
);
/* Change DC servo dither level in startup sequence */
wm8903
_write
(
codec
,
WM8903_WRITE_SEQUENCER_0
,
0x11
);
wm8903
_write
(
codec
,
WM8903_WRITE_SEQUENCER_1
,
0x1257
);
wm8903
_write
(
codec
,
WM8903_WRITE_SEQUENCER_2
,
0x2
);
snd_soc
_write
(
codec
,
WM8903_WRITE_SEQUENCER_0
,
0x11
);
snd_soc
_write
(
codec
,
WM8903_WRITE_SEQUENCER_1
,
0x1257
);
snd_soc
_write
(
codec
,
WM8903_WRITE_SEQUENCER_2
,
0x2
);
wm8903_run_sequence
(
codec
,
0
);
wm8903_sync_reg_cache
(
codec
,
codec
->
reg_cache
);
/* Enable low impedence charge pump output */
reg
=
wm8903
_read
(
codec
,
reg
=
snd_soc
_read
(
codec
,
WM8903_CONTROL_INTERFACE_TEST_1
);
wm8903
_write
(
codec
,
WM8903_CONTROL_INTERFACE_TEST_1
,
snd_soc
_write
(
codec
,
WM8903_CONTROL_INTERFACE_TEST_1
,
reg
|
WM8903_TEST_KEY
);
reg2
=
wm8903
_read
(
codec
,
WM8903_CHARGE_PUMP_TEST_1
);
wm8903
_write
(
codec
,
WM8903_CHARGE_PUMP_TEST_1
,
reg2
=
snd_soc
_read
(
codec
,
WM8903_CHARGE_PUMP_TEST_1
);
snd_soc
_write
(
codec
,
WM8903_CHARGE_PUMP_TEST_1
,
reg2
|
WM8903_CP_SW_KELVIN_MODE_MASK
);
wm8903
_write
(
codec
,
WM8903_CONTROL_INTERFACE_TEST_1
,
snd_soc
_write
(
codec
,
WM8903_CONTROL_INTERFACE_TEST_1
,
reg
);
/* By default no bypass paths are enabled so
* enable Class W support.
*/
dev_dbg
(
&
i2c
->
dev
,
"Enabling Class W
\n
"
);
wm8903
_write
(
codec
,
WM8903_CLASS_W_0
,
reg
|
snd_soc
_write
(
codec
,
WM8903_CLASS_W_0
,
reg
|
WM8903_CP_DYN_FREQ
|
WM8903_CP_DYN_V
);
}
reg
=
wm8903
_read
(
codec
,
WM8903_VMID_CONTROL_0
);
reg
=
snd_soc
_read
(
codec
,
WM8903_VMID_CONTROL_0
);
reg
&=
~
(
WM8903_VMID_RES_MASK
);
reg
|=
WM8903_VMID_RES_250K
;
wm8903
_write
(
codec
,
WM8903_VMID_CONTROL_0
,
reg
);
snd_soc
_write
(
codec
,
WM8903_VMID_CONTROL_0
,
reg
);
break
;
case
SND_SOC_BIAS_OFF
:
wm8903_run_sequence
(
codec
,
32
);
reg
=
wm8903
_read
(
codec
,
WM8903_CLOCK_RATES_2
);
reg
=
snd_soc
_read
(
codec
,
WM8903_CLOCK_RATES_2
);
reg
&=
~
WM8903_CLK_SYS_ENA
;
wm8903
_write
(
codec
,
WM8903_CLOCK_RATES_2
,
reg
);
snd_soc
_write
(
codec
,
WM8903_CLOCK_RATES_2
,
reg
);
break
;
}
...
...
@@ -1081,7 +1005,7 @@ static int wm8903_set_dai_fmt(struct snd_soc_dai *codec_dai,
unsigned
int
fmt
)
{
struct
snd_soc_codec
*
codec
=
codec_dai
->
codec
;
u16
aif1
=
wm8903
_read
(
codec
,
WM8903_AUDIO_INTERFACE_1
);
u16
aif1
=
snd_soc
_read
(
codec
,
WM8903_AUDIO_INTERFACE_1
);
aif1
&=
~
(
WM8903_LRCLK_DIR
|
WM8903_BCLK_DIR
|
WM8903_AIF_FMT_MASK
|
WM8903_AIF_LRCLK_INV
|
WM8903_AIF_BCLK_INV
);
...
...
@@ -1159,7 +1083,7 @@ static int wm8903_set_dai_fmt(struct snd_soc_dai *codec_dai,
return
-
EINVAL
;
}
wm8903
_write
(
codec
,
WM8903_AUDIO_INTERFACE_1
,
aif1
);
snd_soc
_write
(
codec
,
WM8903_AUDIO_INTERFACE_1
,
aif1
);
return
0
;
}
...
...
@@ -1169,14 +1093,14 @@ static int wm8903_digital_mute(struct snd_soc_dai *codec_dai, int mute)
struct
snd_soc_codec
*
codec
=
codec_dai
->
codec
;
u16
reg
;
reg
=
wm8903
_read
(
codec
,
WM8903_DAC_DIGITAL_1
);
reg
=
snd_soc
_read
(
codec
,
WM8903_DAC_DIGITAL_1
);
if
(
mute
)
reg
|=
WM8903_DAC_MUTE
;
else
reg
&=
~
WM8903_DAC_MUTE
;
wm8903
_write
(
codec
,
WM8903_DAC_DIGITAL_1
,
reg
);
snd_soc
_write
(
codec
,
WM8903_DAC_DIGITAL_1
,
reg
);
return
0
;
}
...
...
@@ -1366,12 +1290,12 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream,
int
cur_val
;
int
clk_sys
;
u16
aif1
=
wm8903
_read
(
codec
,
WM8903_AUDIO_INTERFACE_1
);
u16
aif2
=
wm8903
_read
(
codec
,
WM8903_AUDIO_INTERFACE_2
);
u16
aif3
=
wm8903
_read
(
codec
,
WM8903_AUDIO_INTERFACE_3
);
u16
clock0
=
wm8903
_read
(
codec
,
WM8903_CLOCK_RATES_0
);
u16
clock1
=
wm8903
_read
(
codec
,
WM8903_CLOCK_RATES_1
);
u16
dac_digital1
=
wm8903
_read
(
codec
,
WM8903_DAC_DIGITAL_1
);
u16
aif1
=
snd_soc
_read
(
codec
,
WM8903_AUDIO_INTERFACE_1
);
u16
aif2
=
snd_soc
_read
(
codec
,
WM8903_AUDIO_INTERFACE_2
);
u16
aif3
=
snd_soc
_read
(
codec
,
WM8903_AUDIO_INTERFACE_3
);
u16
clock0
=
snd_soc
_read
(
codec
,
WM8903_CLOCK_RATES_0
);
u16
clock1
=
snd_soc
_read
(
codec
,
WM8903_CLOCK_RATES_1
);
u16
dac_digital1
=
snd_soc
_read
(
codec
,
WM8903_DAC_DIGITAL_1
);
if
(
substream
==
wm8903
->
slave_substream
)
{
dev_dbg
(
&
i2c
->
dev
,
"Ignoring hw_params for slave substream
\n
"
);
...
...
@@ -1503,12 +1427,12 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream,
aif2
|=
bclk_divs
[
bclk_div
].
div
;
aif3
|=
bclk
/
fs
;
wm8903
_write
(
codec
,
WM8903_CLOCK_RATES_0
,
clock0
);
wm8903
_write
(
codec
,
WM8903_CLOCK_RATES_1
,
clock1
);
wm8903
_write
(
codec
,
WM8903_AUDIO_INTERFACE_1
,
aif1
);
wm8903
_write
(
codec
,
WM8903_AUDIO_INTERFACE_2
,
aif2
);
wm8903
_write
(
codec
,
WM8903_AUDIO_INTERFACE_3
,
aif3
);
wm8903
_write
(
codec
,
WM8903_DAC_DIGITAL_1
,
dac_digital1
);
snd_soc
_write
(
codec
,
WM8903_CLOCK_RATES_0
,
clock0
);
snd_soc
_write
(
codec
,
WM8903_CLOCK_RATES_1
,
clock1
);
snd_soc
_write
(
codec
,
WM8903_AUDIO_INTERFACE_1
,
aif1
);
snd_soc
_write
(
codec
,
WM8903_AUDIO_INTERFACE_2
,
aif2
);
snd_soc
_write
(
codec
,
WM8903_AUDIO_INTERFACE_3
,
aif3
);
snd_soc
_write
(
codec
,
WM8903_DAC_DIGITAL_1
,
dac_digital1
);
return
0
;
}
...
...
@@ -1593,7 +1517,7 @@ static int wm8903_resume(struct platform_device *pdev)
if
(
tmp_cache
)
{
for
(
i
=
2
;
i
<
ARRAY_SIZE
(
wm8903_reg_defaults
);
i
++
)
if
(
tmp_cache
[
i
]
!=
reg_cache
[
i
])
wm8903
_write
(
codec
,
i
,
tmp_cache
[
i
]);
snd_soc
_write
(
codec
,
i
,
tmp_cache
[
i
]);
}
else
{
dev_err
(
&
i2c
->
dev
,
"Failed to allocate temporary cache
\n
"
);
}
...
...
@@ -1624,9 +1548,6 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c,
codec
->
dev
=
&
i2c
->
dev
;
codec
->
name
=
"WM8903"
;
codec
->
owner
=
THIS_MODULE
;
codec
->
read
=
wm8903_read
;
codec
->
write
=
wm8903_write
;
codec
->
hw_write
=
(
hw_write_t
)
i2c_master_send
;
codec
->
bias_level
=
SND_SOC_BIAS_OFF
;
codec
->
set_bias_level
=
wm8903_set_bias_level
;
codec
->
dai
=
&
wm8903_dai
;
...
...
@@ -1634,18 +1555,25 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c,
codec
->
reg_cache_size
=
ARRAY_SIZE
(
wm8903
->
reg_cache
);
codec
->
reg_cache
=
&
wm8903
->
reg_cache
[
0
];
codec
->
private_data
=
wm8903
;
codec
->
volatile_register
=
wm8903_volatile_register
;
i2c_set_clientdata
(
i2c
,
codec
);
codec
->
control_data
=
i2c
;
val
=
wm8903_hw_read
(
codec
,
WM8903_SW_RESET_AND_ID
);
ret
=
snd_soc_codec_set_cache_io
(
codec
,
8
,
16
,
SND_SOC_I2C
);
if
(
ret
!=
0
)
{
dev_err
(
&
i2c
->
dev
,
"Failed to set cache I/O: %d
\n
"
,
ret
);
goto
err
;
}
val
=
snd_soc_read
(
codec
,
WM8903_SW_RESET_AND_ID
);
if
(
val
!=
wm8903_reg_defaults
[
WM8903_SW_RESET_AND_ID
])
{
dev_err
(
&
i2c
->
dev
,
"Device with ID register %x is not a WM8903
\n
"
,
val
);
return
-
ENODEV
;
}
val
=
wm8903
_read
(
codec
,
WM8903_REVISION_NUMBER
);
val
=
snd_soc
_read
(
codec
,
WM8903_REVISION_NUMBER
);
dev_info
(
&
i2c
->
dev
,
"WM8903 revision %d
\n
"
,
val
&
WM8903_CHIP_REV_MASK
);
...
...
@@ -1655,35 +1583,35 @@ static __devinit int wm8903_i2c_probe(struct i2c_client *i2c,
wm8903_set_bias_level
(
codec
,
SND_SOC_BIAS_STANDBY
);
/* Latch volume update bits */
val
=
wm8903
_read
(
codec
,
WM8903_ADC_DIGITAL_VOLUME_LEFT
);
val
=
snd_soc
_read
(
codec
,
WM8903_ADC_DIGITAL_VOLUME_LEFT
);
val
|=
WM8903_ADCVU
;
wm8903
_write
(
codec
,
WM8903_ADC_DIGITAL_VOLUME_LEFT
,
val
);
wm8903
_write
(
codec
,
WM8903_ADC_DIGITAL_VOLUME_RIGHT
,
val
);
snd_soc
_write
(
codec
,
WM8903_ADC_DIGITAL_VOLUME_LEFT
,
val
);
snd_soc
_write
(
codec
,
WM8903_ADC_DIGITAL_VOLUME_RIGHT
,
val
);
val
=
wm8903
_read
(
codec
,
WM8903_DAC_DIGITAL_VOLUME_LEFT
);
val
=
snd_soc
_read
(
codec
,
WM8903_DAC_DIGITAL_VOLUME_LEFT
);
val
|=
WM8903_DACVU
;
wm8903
_write
(
codec
,
WM8903_DAC_DIGITAL_VOLUME_LEFT
,
val
);
wm8903
_write
(
codec
,
WM8903_DAC_DIGITAL_VOLUME_RIGHT
,
val
);
snd_soc
_write
(
codec
,
WM8903_DAC_DIGITAL_VOLUME_LEFT
,
val
);
snd_soc
_write
(
codec
,
WM8903_DAC_DIGITAL_VOLUME_RIGHT
,
val
);
val
=
wm8903
_read
(
codec
,
WM8903_ANALOGUE_OUT1_LEFT
);
val
=
snd_soc
_read
(
codec
,
WM8903_ANALOGUE_OUT1_LEFT
);
val
|=
WM8903_HPOUTVU
;
wm8903
_write
(
codec
,
WM8903_ANALOGUE_OUT1_LEFT
,
val
);
wm8903
_write
(
codec
,
WM8903_ANALOGUE_OUT1_RIGHT
,
val
);
snd_soc
_write
(
codec
,
WM8903_ANALOGUE_OUT1_LEFT
,
val
);
snd_soc
_write
(
codec
,
WM8903_ANALOGUE_OUT1_RIGHT
,
val
);
val
=
wm8903
_read
(
codec
,
WM8903_ANALOGUE_OUT2_LEFT
);
val
=
snd_soc
_read
(
codec
,
WM8903_ANALOGUE_OUT2_LEFT
);
val
|=
WM8903_LINEOUTVU
;
wm8903
_write
(
codec
,
WM8903_ANALOGUE_OUT2_LEFT
,
val
);
wm8903
_write
(
codec
,
WM8903_ANALOGUE_OUT2_RIGHT
,
val
);
snd_soc
_write
(
codec
,
WM8903_ANALOGUE_OUT2_LEFT
,
val
);
snd_soc
_write
(
codec
,
WM8903_ANALOGUE_OUT2_RIGHT
,
val
);
val
=
wm8903
_read
(
codec
,
WM8903_ANALOGUE_OUT3_LEFT
);
val
=
snd_soc
_read
(
codec
,
WM8903_ANALOGUE_OUT3_LEFT
);
val
|=
WM8903_SPKVU
;
wm8903
_write
(
codec
,
WM8903_ANALOGUE_OUT3_LEFT
,
val
);
wm8903
_write
(
codec
,
WM8903_ANALOGUE_OUT3_RIGHT
,
val
);
snd_soc
_write
(
codec
,
WM8903_ANALOGUE_OUT3_LEFT
,
val
);
snd_soc
_write
(
codec
,
WM8903_ANALOGUE_OUT3_RIGHT
,
val
);
/* Enable DAC soft mute by default */
val
=
wm8903
_read
(
codec
,
WM8903_DAC_DIGITAL_1
);
val
=
snd_soc
_read
(
codec
,
WM8903_DAC_DIGITAL_1
);
val
|=
WM8903_DAC_MUTEMODE
;
wm8903
_write
(
codec
,
WM8903_DAC_DIGITAL_1
,
val
);
snd_soc
_write
(
codec
,
WM8903_DAC_DIGITAL_1
,
val
);
wm8903_dai
.
dev
=
&
i2c
->
dev
;
wm8903_codec
=
codec
;
...
...
sound/soc/codecs/wm8940.c
View file @
06cddefc
...
...
@@ -106,50 +106,6 @@ static u16 wm8940_reg_defaults[] = {
0x0000
,
/* Mono Mixer Control */
};
static
inline
unsigned
int
wm8940_read_reg_cache
(
struct
snd_soc_codec
*
codec
,
unsigned
int
reg
)
{
u16
*
cache
=
codec
->
reg_cache
;
if
(
reg
>=
ARRAY_SIZE
(
wm8940_reg_defaults
))
return
-
1
;
return
cache
[
reg
];
}
static
inline
int
wm8940_write_reg_cache
(
struct
snd_soc_codec
*
codec
,
u16
reg
,
unsigned
int
value
)
{
u16
*
cache
=
codec
->
reg_cache
;
if
(
reg
>=
ARRAY_SIZE
(
wm8940_reg_defaults
))
return
-
1
;
cache
[
reg
]
=
value
;
return
0
;
}
static
int
wm8940_write
(
struct
snd_soc_codec
*
codec
,
unsigned
int
reg
,
unsigned
int
value
)
{
int
ret
;
u8
data
[
3
]
=
{
reg
,
(
value
&
0xff00
)
>>
8
,
(
value
&
0x00ff
)
};
wm8940_write_reg_cache
(
codec
,
reg
,
value
);
ret
=
codec
->
hw_write
(
codec
->
control_data
,
data
,
3
);
if
(
ret
<
0
)
return
ret
;
else
if
(
ret
!=
3
)
return
-
EIO
;
return
0
;
}
static
const
char
*
wm8940_companding
[]
=
{
"Off"
,
"NC"
,
"u-law"
,
"A-law"
};
static
const
struct
soc_enum
wm8940_adc_companding_enum
=
SOC_ENUM_SINGLE
(
WM8940_COMPANDINGCTL
,
1
,
4
,
wm8940_companding
);
...
...
@@ -348,14 +304,14 @@ static int wm8940_add_widgets(struct snd_soc_codec *codec)
return
ret
;
}
#define wm8940_reset(c)
wm8940
_write(c, WM8940_SOFTRESET, 0);
#define wm8940_reset(c)
snd_soc
_write(c, WM8940_SOFTRESET, 0);
static
int
wm8940_set_dai_fmt
(
struct
snd_soc_dai
*
codec_dai
,
unsigned
int
fmt
)
{
struct
snd_soc_codec
*
codec
=
codec_dai
->
codec
;
u16
iface
=
wm8940_read_reg_cache
(
codec
,
WM8940_IFACE
)
&
0xFE67
;
u16
clk
=
wm8940_read_reg_cache
(
codec
,
WM8940_CLOCK
)
&
0x1fe
;
u16
iface
=
snd_soc_read
(
codec
,
WM8940_IFACE
)
&
0xFE67
;
u16
clk
=
snd_soc_read
(
codec
,
WM8940_CLOCK
)
&
0x1fe
;
switch
(
fmt
&
SND_SOC_DAIFMT_MASTER_MASK
)
{
case
SND_SOC_DAIFMT_CBM_CFM
:
...
...
@@ -366,7 +322,7 @@ static int wm8940_set_dai_fmt(struct snd_soc_dai *codec_dai,
default:
return
-
EINVAL
;
}
wm8940
_write
(
codec
,
WM8940_CLOCK
,
clk
);
snd_soc
_write
(
codec
,
WM8940_CLOCK
,
clk
);
switch
(
fmt
&
SND_SOC_DAIFMT_FORMAT_MASK
)
{
case
SND_SOC_DAIFMT_I2S
:
...
...
@@ -399,7 +355,7 @@ static int wm8940_set_dai_fmt(struct snd_soc_dai *codec_dai,
break
;
}
wm8940
_write
(
codec
,
WM8940_IFACE
,
iface
);
snd_soc
_write
(
codec
,
WM8940_IFACE
,
iface
);
return
0
;
}
...
...
@@ -411,9 +367,9 @@ static int wm8940_i2s_hw_params(struct snd_pcm_substream *substream,
struct
snd_soc_pcm_runtime
*
rtd
=
substream
->
private_data
;
struct
snd_soc_device
*
socdev
=
rtd
->
socdev
;
struct
snd_soc_codec
*
codec
=
socdev
->
card
->
codec
;
u16
iface
=
wm8940_read_reg_cache
(
codec
,
WM8940_IFACE
)
&
0xFD9F
;
u16
addcntrl
=
wm8940_read_reg_cache
(
codec
,
WM8940_ADDCNTRL
)
&
0xFFF1
;
u16
companding
=
wm8940_read_reg_cache
(
codec
,
u16
iface
=
snd_soc_read
(
codec
,
WM8940_IFACE
)
&
0xFD9F
;
u16
addcntrl
=
snd_soc_read
(
codec
,
WM8940_ADDCNTRL
)
&
0xFFF1
;
u16
companding
=
snd_soc_read
(
codec
,
WM8940_COMPANDINGCTL
)
&
0xFFDF
;
int
ret
;
...
...
@@ -442,7 +398,7 @@ static int wm8940_i2s_hw_params(struct snd_pcm_substream *substream,
case
SNDRV_PCM_RATE_48000
:
break
;
}
ret
=
wm8940
_write
(
codec
,
WM8940_ADDCNTRL
,
addcntrl
);
ret
=
snd_soc
_write
(
codec
,
WM8940_ADDCNTRL
,
addcntrl
);
if
(
ret
)
goto
error_ret
;
...
...
@@ -462,10 +418,10 @@ static int wm8940_i2s_hw_params(struct snd_pcm_substream *substream,
iface
|=
(
3
<<
5
);
break
;
}
ret
=
wm8940
_write
(
codec
,
WM8940_COMPANDINGCTL
,
companding
);
ret
=
snd_soc
_write
(
codec
,
WM8940_COMPANDINGCTL
,
companding
);
if
(
ret
)
goto
error_ret
;
ret
=
wm8940
_write
(
codec
,
WM8940_IFACE
,
iface
);
ret
=
snd_soc
_write
(
codec
,
WM8940_IFACE
,
iface
);
error_ret:
return
ret
;
...
...
@@ -474,19 +430,19 @@ static int wm8940_i2s_hw_params(struct snd_pcm_substream *substream,
static
int
wm8940_mute
(
struct
snd_soc_dai
*
dai
,
int
mute
)
{
struct
snd_soc_codec
*
codec
=
dai
->
codec
;
u16
mute_reg
=
wm8940_read_reg_cache
(
codec
,
WM8940_DAC
)
&
0xffbf
;
u16
mute_reg
=
snd_soc_read
(
codec
,
WM8940_DAC
)
&
0xffbf
;
if
(
mute
)
mute_reg
|=
0x40
;
return
wm8940
_write
(
codec
,
WM8940_DAC
,
mute_reg
);
return
snd_soc
_write
(
codec
,
WM8940_DAC
,
mute_reg
);
}
static
int
wm8940_set_bias_level
(
struct
snd_soc_codec
*
codec
,
enum
snd_soc_bias_level
level
)
{
u16
val
;
u16
pwr_reg
=
wm8940_read_reg_cache
(
codec
,
WM8940_POWER1
)
&
0x1F0
;
u16
pwr_reg
=
snd_soc_read
(
codec
,
WM8940_POWER1
)
&
0x1F0
;
int
ret
=
0
;
switch
(
level
)
{
...
...
@@ -494,26 +450,26 @@ static int wm8940_set_bias_level(struct snd_soc_codec *codec,
/* ensure bufioen and biasen */
pwr_reg
|=
(
1
<<
2
)
|
(
1
<<
3
);
/* Enable thermal shutdown */
val
=
wm8940_read_reg_cache
(
codec
,
WM8940_OUTPUTCTL
);
ret
=
wm8940
_write
(
codec
,
WM8940_OUTPUTCTL
,
val
|
0x2
);
val
=
snd_soc_read
(
codec
,
WM8940_OUTPUTCTL
);
ret
=
snd_soc
_write
(
codec
,
WM8940_OUTPUTCTL
,
val
|
0x2
);
if
(
ret
)
break
;
/* set vmid to 75k */
ret
=
wm8940
_write
(
codec
,
WM8940_POWER1
,
pwr_reg
|
0x1
);
ret
=
snd_soc
_write
(
codec
,
WM8940_POWER1
,
pwr_reg
|
0x1
);
break
;
case
SND_SOC_BIAS_PREPARE
:
/* ensure bufioen and biasen */
pwr_reg
|=
(
1
<<
2
)
|
(
1
<<
3
);
ret
=
wm8940
_write
(
codec
,
WM8940_POWER1
,
pwr_reg
|
0x1
);
ret
=
snd_soc
_write
(
codec
,
WM8940_POWER1
,
pwr_reg
|
0x1
);
break
;
case
SND_SOC_BIAS_STANDBY
:
/* ensure bufioen and biasen */
pwr_reg
|=
(
1
<<
2
)
|
(
1
<<
3
);
/* set vmid to 300k for standby */
ret
=
wm8940
_write
(
codec
,
WM8940_POWER1
,
pwr_reg
|
0x2
);
ret
=
snd_soc
_write
(
codec
,
WM8940_POWER1
,
pwr_reg
|
0x2
);
break
;
case
SND_SOC_BIAS_OFF
:
ret
=
wm8940
_write
(
codec
,
WM8940_POWER1
,
pwr_reg
);
ret
=
snd_soc
_write
(
codec
,
WM8940_POWER1
,
pwr_reg
);
break
;
}
...
...
@@ -587,36 +543,36 @@ static int wm8940_set_dai_pll(struct snd_soc_dai *codec_dai,
u16
reg
;
/* Turn off PLL */
reg
=
wm8940_read_reg_cache
(
codec
,
WM8940_POWER1
);
wm8940
_write
(
codec
,
WM8940_POWER1
,
reg
&
0x1df
);
reg
=
snd_soc_read
(
codec
,
WM8940_POWER1
);
snd_soc
_write
(
codec
,
WM8940_POWER1
,
reg
&
0x1df
);
if
(
freq_in
==
0
||
freq_out
==
0
)
{
/* Clock CODEC directly from MCLK */
reg
=
wm8940_read_reg_cache
(
codec
,
WM8940_CLOCK
);
wm8940
_write
(
codec
,
WM8940_CLOCK
,
reg
&
0x0ff
);
reg
=
snd_soc_read
(
codec
,
WM8940_CLOCK
);
snd_soc
_write
(
codec
,
WM8940_CLOCK
,
reg
&
0x0ff
);
/* Pll power down */
wm8940
_write
(
codec
,
WM8940_PLLN
,
(
1
<<
7
));
snd_soc
_write
(
codec
,
WM8940_PLLN
,
(
1
<<
7
));
return
0
;
}
/* Pll is followed by a frequency divide by 4 */
pll_factors
(
freq_out
*
4
,
freq_in
);
if
(
pll_div
.
k
)
wm8940
_write
(
codec
,
WM8940_PLLN
,
snd_soc
_write
(
codec
,
WM8940_PLLN
,
(
pll_div
.
pre_scale
<<
4
)
|
pll_div
.
n
|
(
1
<<
6
));
else
/* No factional component */
wm8940
_write
(
codec
,
WM8940_PLLN
,
snd_soc
_write
(
codec
,
WM8940_PLLN
,
(
pll_div
.
pre_scale
<<
4
)
|
pll_div
.
n
);
wm8940
_write
(
codec
,
WM8940_PLLK1
,
pll_div
.
k
>>
18
);
wm8940
_write
(
codec
,
WM8940_PLLK2
,
(
pll_div
.
k
>>
9
)
&
0x1ff
);
wm8940
_write
(
codec
,
WM8940_PLLK3
,
pll_div
.
k
&
0x1ff
);
snd_soc
_write
(
codec
,
WM8940_PLLK1
,
pll_div
.
k
>>
18
);
snd_soc
_write
(
codec
,
WM8940_PLLK2
,
(
pll_div
.
k
>>
9
)
&
0x1ff
);
snd_soc
_write
(
codec
,
WM8940_PLLK3
,
pll_div
.
k
&
0x1ff
);
/* Enable the PLL */
reg
=
wm8940_read_reg_cache
(
codec
,
WM8940_POWER1
);
wm8940
_write
(
codec
,
WM8940_POWER1
,
reg
|
0x020
);
reg
=
snd_soc_read
(
codec
,
WM8940_POWER1
);
snd_soc
_write
(
codec
,
WM8940_POWER1
,
reg
|
0x020
);
/* Run CODEC from PLL instead of MCLK */
reg
=
wm8940_read_reg_cache
(
codec
,
WM8940_CLOCK
);
wm8940
_write
(
codec
,
WM8940_CLOCK
,
reg
|
0x100
);
reg
=
snd_soc_read
(
codec
,
WM8940_CLOCK
);
snd_soc
_write
(
codec
,
WM8940_CLOCK
,
reg
|
0x100
);
return
0
;
}
...
...
@@ -648,16 +604,16 @@ static int wm8940_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
switch
(
div_id
)
{
case
WM8940_BCLKDIV
:
reg
=
wm8940_read_reg_cache
(
codec
,
WM8940_CLOCK
)
&
0xFFEF3
;
ret
=
wm8940
_write
(
codec
,
WM8940_CLOCK
,
reg
|
(
div
<<
2
));
reg
=
snd_soc_read
(
codec
,
WM8940_CLOCK
)
&
0xFFEF3
;
ret
=
snd_soc
_write
(
codec
,
WM8940_CLOCK
,
reg
|
(
div
<<
2
));
break
;
case
WM8940_MCLKDIV
:
reg
=
wm8940_read_reg_cache
(
codec
,
WM8940_CLOCK
)
&
0xFF1F
;
ret
=
wm8940
_write
(
codec
,
WM8940_CLOCK
,
reg
|
(
div
<<
5
));
reg
=
snd_soc_read
(
codec
,
WM8940_CLOCK
)
&
0xFF1F
;
ret
=
snd_soc
_write
(
codec
,
WM8940_CLOCK
,
reg
|
(
div
<<
5
));
break
;
case
WM8940_OPCLKDIV
:
reg
=
wm8940_read_reg_cache
(
codec
,
WM8940_ADDCNTRL
)
&
0xFFCF
;
ret
=
wm8940
_write
(
codec
,
WM8940_ADDCNTRL
,
reg
|
(
div
<<
4
));
reg
=
snd_soc_read
(
codec
,
WM8940_ADDCNTRL
)
&
0xFFCF
;
ret
=
snd_soc
_write
(
codec
,
WM8940_ADDCNTRL
,
reg
|
(
div
<<
4
));
break
;
}
return
ret
;
...
...
@@ -808,7 +764,8 @@ struct snd_soc_codec_device soc_codec_dev_wm8940 = {
};
EXPORT_SYMBOL_GPL
(
soc_codec_dev_wm8940
);
static
int
wm8940_register
(
struct
wm8940_priv
*
wm8940
)
static
int
wm8940_register
(
struct
wm8940_priv
*
wm8940
,
enum
snd_soc_control_type
control
)
{
struct
wm8940_setup_data
*
pdata
=
wm8940
->
codec
.
dev
->
platform_data
;
struct
snd_soc_codec
*
codec
=
&
wm8940
->
codec
;
...
...
@@ -825,8 +782,6 @@ static int wm8940_register(struct wm8940_priv *wm8940)
codec
->
private_data
=
wm8940
;
codec
->
name
=
"WM8940"
;
codec
->
owner
=
THIS_MODULE
;
codec
->
read
=
wm8940_read_reg_cache
;
codec
->
write
=
wm8940_write
;
codec
->
bias_level
=
SND_SOC_BIAS_OFF
;
codec
->
set_bias_level
=
wm8940_set_bias_level
;
codec
->
dai
=
&
wm8940_dai
;
...
...
@@ -834,6 +789,12 @@ static int wm8940_register(struct wm8940_priv *wm8940)
codec
->
reg_cache_size
=
ARRAY_SIZE
(
wm8940_reg_defaults
);
codec
->
reg_cache
=
&
wm8940
->
reg_cache
;
ret
=
snd_soc_codec_set_cache_io
(
codec
,
8
,
16
,
control
);
if
(
ret
==
0
)
{
dev_err
(
codec
->
dev
,
"Failed to set cache I/O: %d
\n
"
,
ret
);
return
ret
;
}
memcpy
(
codec
->
reg_cache
,
wm8940_reg_defaults
,
sizeof
(
wm8940_reg_defaults
));
...
...
@@ -847,15 +808,15 @@ static int wm8940_register(struct wm8940_priv *wm8940)
wm8940_set_bias_level
(
codec
,
SND_SOC_BIAS_STANDBY
);
ret
=
wm8940
_write
(
codec
,
WM8940_POWER1
,
0x180
);
ret
=
snd_soc
_write
(
codec
,
WM8940_POWER1
,
0x180
);
if
(
ret
<
0
)
return
ret
;
if
(
!
pdata
)
dev_warn
(
codec
->
dev
,
"No platform data supplied
\n
"
);
else
{
reg
=
wm8940_read_reg_cache
(
codec
,
WM8940_OUTPUTCTL
);
ret
=
wm8940
_write
(
codec
,
WM8940_OUTPUTCTL
,
reg
|
pdata
->
vroi
);
reg
=
snd_soc_read
(
codec
,
WM8940_OUTPUTCTL
);
ret
=
snd_soc
_write
(
codec
,
WM8940_OUTPUTCTL
,
reg
|
pdata
->
vroi
);
if
(
ret
<
0
)
return
ret
;
}
...
...
@@ -904,7 +865,7 @@ static int wm8940_i2c_probe(struct i2c_client *i2c,
codec
->
control_data
=
i2c
;
codec
->
dev
=
&
i2c
->
dev
;
return
wm8940_register
(
wm8940
);
return
wm8940_register
(
wm8940
,
SND_SOC_I2C
);
}
static
int
__devexit
wm8940_i2c_remove
(
struct
i2c_client
*
client
)
...
...
sound/soc/codecs/wm8960.c
View file @
06cddefc
...
...
@@ -69,61 +69,7 @@ struct wm8960_priv {
struct
snd_soc_codec
codec
;
};
/*
* read wm8960 register cache
*/
static
inline
unsigned
int
wm8960_read_reg_cache
(
struct
snd_soc_codec
*
codec
,
unsigned
int
reg
)
{
u16
*
cache
=
codec
->
reg_cache
;
if
(
reg
==
WM8960_RESET
)
return
0
;
if
(
reg
>=
WM8960_CACHEREGNUM
)
return
-
1
;
return
cache
[
reg
];
}
/*
* write wm8960 register cache
*/
static
inline
void
wm8960_write_reg_cache
(
struct
snd_soc_codec
*
codec
,
u16
reg
,
unsigned
int
value
)
{
u16
*
cache
=
codec
->
reg_cache
;
if
(
reg
>=
WM8960_CACHEREGNUM
)
return
;
cache
[
reg
]
=
value
;
}
static
inline
unsigned
int
wm8960_read
(
struct
snd_soc_codec
*
codec
,
unsigned
int
reg
)
{
return
wm8960_read_reg_cache
(
codec
,
reg
);
}
/*
* write to the WM8960 register space
*/
static
int
wm8960_write
(
struct
snd_soc_codec
*
codec
,
unsigned
int
reg
,
unsigned
int
value
)
{
u8
data
[
2
];
/* data is
* D15..D9 WM8960 register offset
* D8...D0 register data
*/
data
[
0
]
=
(
reg
<<
1
)
|
((
value
>>
8
)
&
0x0001
);
data
[
1
]
=
value
&
0x00ff
;
wm8960_write_reg_cache
(
codec
,
reg
,
value
);
if
(
codec
->
hw_write
(
codec
->
control_data
,
data
,
2
)
==
2
)
return
0
;
else
return
-
EIO
;
}
#define wm8960_reset(c) wm8960_write(c, WM8960_RESET, 0)
#define wm8960_reset(c) snd_soc_write(c, WM8960_RESET, 0)
/* enumerated controls */
static
const
char
*
wm8960_deemph
[]
=
{
"None"
,
"32Khz"
,
"44.1Khz"
,
"48Khz"
};
...
...
@@ -420,7 +366,7 @@ static int wm8960_set_dai_fmt(struct snd_soc_dai *codec_dai,
}
/* set iface */
wm8960
_write
(
codec
,
WM8960_IFACE1
,
iface
);
snd_soc
_write
(
codec
,
WM8960_IFACE1
,
iface
);
return
0
;
}
...
...
@@ -431,7 +377,7 @@ static int wm8960_hw_params(struct snd_pcm_substream *substream,
struct
snd_soc_pcm_runtime
*
rtd
=
substream
->
private_data
;
struct
snd_soc_device
*
socdev
=
rtd
->
socdev
;
struct
snd_soc_codec
*
codec
=
socdev
->
card
->
codec
;
u16
iface
=
wm8960
_read
(
codec
,
WM8960_IFACE1
)
&
0xfff3
;
u16
iface
=
snd_soc
_read
(
codec
,
WM8960_IFACE1
)
&
0xfff3
;
/* bit size */
switch
(
params_format
(
params
))
{
...
...
@@ -446,19 +392,19 @@ static int wm8960_hw_params(struct snd_pcm_substream *substream,
}
/* set iface */
wm8960
_write
(
codec
,
WM8960_IFACE1
,
iface
);
snd_soc
_write
(
codec
,
WM8960_IFACE1
,
iface
);
return
0
;
}
static
int
wm8960_mute
(
struct
snd_soc_dai
*
dai
,
int
mute
)
{
struct
snd_soc_codec
*
codec
=
dai
->
codec
;
u16
mute_reg
=
wm8960
_read
(
codec
,
WM8960_DACCTL1
)
&
0xfff7
;
u16
mute_reg
=
snd_soc
_read
(
codec
,
WM8960_DACCTL1
)
&
0xfff7
;
if
(
mute
)
wm8960
_write
(
codec
,
WM8960_DACCTL1
,
mute_reg
|
0x8
);
snd_soc
_write
(
codec
,
WM8960_DACCTL1
,
mute_reg
|
0x8
);
else
wm8960
_write
(
codec
,
WM8960_DACCTL1
,
mute_reg
);
snd_soc
_write
(
codec
,
WM8960_DACCTL1
,
mute_reg
);
return
0
;
}
...
...
@@ -474,16 +420,16 @@ static int wm8960_set_bias_level(struct snd_soc_codec *codec,
case
SND_SOC_BIAS_PREPARE
:
/* Set VMID to 2x50k */
reg
=
wm8960
_read
(
codec
,
WM8960_POWER1
);
reg
=
snd_soc
_read
(
codec
,
WM8960_POWER1
);
reg
&=
~
0x180
;
reg
|=
0x80
;
wm8960
_write
(
codec
,
WM8960_POWER1
,
reg
);
snd_soc
_write
(
codec
,
WM8960_POWER1
,
reg
);
break
;
case
SND_SOC_BIAS_STANDBY
:
if
(
codec
->
bias_level
==
SND_SOC_BIAS_OFF
)
{
/* Enable anti-pop features */
wm8960
_write
(
codec
,
WM8960_APOP1
,
snd_soc
_write
(
codec
,
WM8960_APOP1
,
WM8960_POBCTRL
|
WM8960_SOFT_ST
|
WM8960_BUFDCOPEN
|
WM8960_BUFIOEN
);
...
...
@@ -491,43 +437,43 @@ static int wm8960_set_bias_level(struct snd_soc_codec *codec,
reg
=
WM8960_DISOP
;
if
(
pdata
)
reg
|=
pdata
->
dres
<<
4
;
wm8960
_write
(
codec
,
WM8960_APOP2
,
reg
);
snd_soc
_write
(
codec
,
WM8960_APOP2
,
reg
);
msleep
(
400
);
wm8960
_write
(
codec
,
WM8960_APOP2
,
0
);
snd_soc
_write
(
codec
,
WM8960_APOP2
,
0
);
/* Enable & ramp VMID at 2x50k */
reg
=
wm8960
_read
(
codec
,
WM8960_POWER1
);
reg
=
snd_soc
_read
(
codec
,
WM8960_POWER1
);
reg
|=
0x80
;
wm8960
_write
(
codec
,
WM8960_POWER1
,
reg
);
snd_soc
_write
(
codec
,
WM8960_POWER1
,
reg
);
msleep
(
100
);
/* Enable VREF */
wm8960
_write
(
codec
,
WM8960_POWER1
,
reg
|
WM8960_VREF
);
snd_soc
_write
(
codec
,
WM8960_POWER1
,
reg
|
WM8960_VREF
);
/* Disable anti-pop features */
wm8960
_write
(
codec
,
WM8960_APOP1
,
WM8960_BUFIOEN
);
snd_soc
_write
(
codec
,
WM8960_APOP1
,
WM8960_BUFIOEN
);
}
/* Set VMID to 2x250k */
reg
=
wm8960
_read
(
codec
,
WM8960_POWER1
);
reg
=
snd_soc
_read
(
codec
,
WM8960_POWER1
);
reg
&=
~
0x180
;
reg
|=
0x100
;
wm8960
_write
(
codec
,
WM8960_POWER1
,
reg
);
snd_soc
_write
(
codec
,
WM8960_POWER1
,
reg
);
break
;
case
SND_SOC_BIAS_OFF
:
/* Enable anti-pop features */
wm8960
_write
(
codec
,
WM8960_APOP1
,
snd_soc
_write
(
codec
,
WM8960_APOP1
,
WM8960_POBCTRL
|
WM8960_SOFT_ST
|
WM8960_BUFDCOPEN
|
WM8960_BUFIOEN
);
/* Disable VMID and VREF, let them discharge */
wm8960
_write
(
codec
,
WM8960_POWER1
,
0
);
snd_soc
_write
(
codec
,
WM8960_POWER1
,
0
);
msleep
(
600
);
wm8960
_write
(
codec
,
WM8960_APOP1
,
0
);
snd_soc
_write
(
codec
,
WM8960_APOP1
,
0
);
break
;
}
...
...
@@ -610,33 +556,33 @@ static int wm8960_set_dai_pll(struct snd_soc_dai *codec_dai,
/* Disable the PLL: even if we are changing the frequency the
* PLL needs to be disabled while we do so. */
wm8960
_write
(
codec
,
WM8960_CLOCK1
,
wm8960
_read
(
codec
,
WM8960_CLOCK1
)
&
~
1
);
wm8960
_write
(
codec
,
WM8960_POWER2
,
wm8960
_read
(
codec
,
WM8960_POWER2
)
&
~
1
);
snd_soc
_write
(
codec
,
WM8960_CLOCK1
,
snd_soc
_read
(
codec
,
WM8960_CLOCK1
)
&
~
1
);
snd_soc
_write
(
codec
,
WM8960_POWER2
,
snd_soc
_read
(
codec
,
WM8960_POWER2
)
&
~
1
);
if
(
!
freq_in
||
!
freq_out
)
return
0
;
reg
=
wm8960
_read
(
codec
,
WM8960_PLL1
)
&
~
0x3f
;
reg
=
snd_soc
_read
(
codec
,
WM8960_PLL1
)
&
~
0x3f
;
reg
|=
pll_div
.
pre_div
<<
4
;
reg
|=
pll_div
.
n
;
if
(
pll_div
.
k
)
{
reg
|=
0x20
;
wm8960
_write
(
codec
,
WM8960_PLL2
,
(
pll_div
.
k
>>
18
)
&
0x3f
);
wm8960
_write
(
codec
,
WM8960_PLL3
,
(
pll_div
.
k
>>
9
)
&
0x1ff
);
wm8960
_write
(
codec
,
WM8960_PLL4
,
pll_div
.
k
&
0x1ff
);
snd_soc
_write
(
codec
,
WM8960_PLL2
,
(
pll_div
.
k
>>
18
)
&
0x3f
);
snd_soc
_write
(
codec
,
WM8960_PLL3
,
(
pll_div
.
k
>>
9
)
&
0x1ff
);
snd_soc
_write
(
codec
,
WM8960_PLL4
,
pll_div
.
k
&
0x1ff
);
}
wm8960
_write
(
codec
,
WM8960_PLL1
,
reg
);
snd_soc
_write
(
codec
,
WM8960_PLL1
,
reg
);
/* Turn it on */
wm8960
_write
(
codec
,
WM8960_POWER2
,
wm8960
_read
(
codec
,
WM8960_POWER2
)
|
1
);
snd_soc
_write
(
codec
,
WM8960_POWER2
,
snd_soc
_read
(
codec
,
WM8960_POWER2
)
|
1
);
msleep
(
250
);
wm8960
_write
(
codec
,
WM8960_CLOCK1
,
wm8960
_read
(
codec
,
WM8960_CLOCK1
)
|
1
);
snd_soc
_write
(
codec
,
WM8960_CLOCK1
,
snd_soc
_read
(
codec
,
WM8960_CLOCK1
)
|
1
);
return
0
;
}
...
...
@@ -649,28 +595,28 @@ static int wm8960_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
switch
(
div_id
)
{
case
WM8960_SYSCLKSEL
:
reg
=
wm8960
_read
(
codec
,
WM8960_CLOCK1
)
&
0x1fe
;
wm8960
_write
(
codec
,
WM8960_CLOCK1
,
reg
|
div
);
reg
=
snd_soc
_read
(
codec
,
WM8960_CLOCK1
)
&
0x1fe
;
snd_soc
_write
(
codec
,
WM8960_CLOCK1
,
reg
|
div
);
break
;
case
WM8960_SYSCLKDIV
:
reg
=
wm8960
_read
(
codec
,
WM8960_CLOCK1
)
&
0x1f9
;
wm8960
_write
(
codec
,
WM8960_CLOCK1
,
reg
|
div
);
reg
=
snd_soc
_read
(
codec
,
WM8960_CLOCK1
)
&
0x1f9
;
snd_soc
_write
(
codec
,
WM8960_CLOCK1
,
reg
|
div
);
break
;
case
WM8960_DACDIV
:
reg
=
wm8960
_read
(
codec
,
WM8960_CLOCK1
)
&
0x1c7
;
wm8960
_write
(
codec
,
WM8960_CLOCK1
,
reg
|
div
);
reg
=
snd_soc
_read
(
codec
,
WM8960_CLOCK1
)
&
0x1c7
;
snd_soc
_write
(
codec
,
WM8960_CLOCK1
,
reg
|
div
);
break
;
case
WM8960_OPCLKDIV
:
reg
=
wm8960
_read
(
codec
,
WM8960_PLL1
)
&
0x03f
;
wm8960
_write
(
codec
,
WM8960_PLL1
,
reg
|
div
);
reg
=
snd_soc
_read
(
codec
,
WM8960_PLL1
)
&
0x03f
;
snd_soc
_write
(
codec
,
WM8960_PLL1
,
reg
|
div
);
break
;
case
WM8960_DCLKDIV
:
reg
=
wm8960
_read
(
codec
,
WM8960_CLOCK2
)
&
0x03f
;
wm8960
_write
(
codec
,
WM8960_CLOCK2
,
reg
|
div
);
reg
=
snd_soc
_read
(
codec
,
WM8960_CLOCK2
)
&
0x03f
;
snd_soc
_write
(
codec
,
WM8960_CLOCK2
,
reg
|
div
);
break
;
case
WM8960_TOCLKSEL
:
reg
=
wm8960
_read
(
codec
,
WM8960_ADDCTL1
)
&
0x1fd
;
wm8960
_write
(
codec
,
WM8960_ADDCTL1
,
reg
|
div
);
reg
=
snd_soc
_read
(
codec
,
WM8960_ADDCTL1
)
&
0x1fd
;
snd_soc
_write
(
codec
,
WM8960_ADDCTL1
,
reg
|
div
);
break
;
default:
return
-
EINVAL
;
...
...
@@ -801,7 +747,8 @@ struct snd_soc_codec_device soc_codec_dev_wm8960 = {
};
EXPORT_SYMBOL_GPL
(
soc_codec_dev_wm8960
);
static
int
wm8960_register
(
struct
wm8960_priv
*
wm8960
)
static
int
wm8960_register
(
struct
wm8960_priv
*
wm8960
,
enum
snd_soc_control_type
control
)
{
struct
wm8960_data
*
pdata
=
wm8960
->
codec
.
dev
->
platform_data
;
struct
snd_soc_codec
*
codec
=
&
wm8960
->
codec
;
...
...
@@ -830,8 +777,6 @@ static int wm8960_register(struct wm8960_priv *wm8960)
codec
->
private_data
=
wm8960
;
codec
->
name
=
"WM8960"
;
codec
->
owner
=
THIS_MODULE
;
codec
->
read
=
wm8960_read_reg_cache
;
codec
->
write
=
wm8960_write
;
codec
->
bias_level
=
SND_SOC_BIAS_OFF
;
codec
->
set_bias_level
=
wm8960_set_bias_level
;
codec
->
dai
=
&
wm8960_dai
;
...
...
@@ -841,6 +786,12 @@ static int wm8960_register(struct wm8960_priv *wm8960)
memcpy
(
codec
->
reg_cache
,
wm8960_reg
,
sizeof
(
wm8960_reg
));
ret
=
snd_soc_codec_set_cache_io
(
codec
,
7
,
9
,
control
);
if
(
ret
<
0
)
{
dev_err
(
codec
->
dev
,
"Failed to set cache I/O: %d
\n
"
,
ret
);
goto
err
;
}
ret
=
wm8960_reset
(
codec
);
if
(
ret
<
0
)
{
dev_err
(
codec
->
dev
,
"Failed to issue reset
\n
"
);
...
...
@@ -852,26 +803,26 @@ static int wm8960_register(struct wm8960_priv *wm8960)
wm8960_set_bias_level
(
codec
,
SND_SOC_BIAS_STANDBY
);
/* Latch the update bits */
reg
=
wm8960
_read
(
codec
,
WM8960_LINVOL
);
wm8960
_write
(
codec
,
WM8960_LINVOL
,
reg
|
0x100
);
reg
=
wm8960
_read
(
codec
,
WM8960_RINVOL
);
wm8960
_write
(
codec
,
WM8960_RINVOL
,
reg
|
0x100
);
reg
=
wm8960
_read
(
codec
,
WM8960_LADC
);
wm8960
_write
(
codec
,
WM8960_LADC
,
reg
|
0x100
);
reg
=
wm8960
_read
(
codec
,
WM8960_RADC
);
wm8960
_write
(
codec
,
WM8960_RADC
,
reg
|
0x100
);
reg
=
wm8960
_read
(
codec
,
WM8960_LDAC
);
wm8960
_write
(
codec
,
WM8960_LDAC
,
reg
|
0x100
);
reg
=
wm8960
_read
(
codec
,
WM8960_RDAC
);
wm8960
_write
(
codec
,
WM8960_RDAC
,
reg
|
0x100
);
reg
=
wm8960
_read
(
codec
,
WM8960_LOUT1
);
wm8960
_write
(
codec
,
WM8960_LOUT1
,
reg
|
0x100
);
reg
=
wm8960
_read
(
codec
,
WM8960_ROUT1
);
wm8960
_write
(
codec
,
WM8960_ROUT1
,
reg
|
0x100
);
reg
=
wm8960
_read
(
codec
,
WM8960_LOUT2
);
wm8960
_write
(
codec
,
WM8960_LOUT2
,
reg
|
0x100
);
reg
=
wm8960
_read
(
codec
,
WM8960_ROUT2
);
wm8960
_write
(
codec
,
WM8960_ROUT2
,
reg
|
0x100
);
reg
=
snd_soc
_read
(
codec
,
WM8960_LINVOL
);
snd_soc
_write
(
codec
,
WM8960_LINVOL
,
reg
|
0x100
);
reg
=
snd_soc
_read
(
codec
,
WM8960_RINVOL
);
snd_soc
_write
(
codec
,
WM8960_RINVOL
,
reg
|
0x100
);
reg
=
snd_soc
_read
(
codec
,
WM8960_LADC
);
snd_soc
_write
(
codec
,
WM8960_LADC
,
reg
|
0x100
);
reg
=
snd_soc
_read
(
codec
,
WM8960_RADC
);
snd_soc
_write
(
codec
,
WM8960_RADC
,
reg
|
0x100
);
reg
=
snd_soc
_read
(
codec
,
WM8960_LDAC
);
snd_soc
_write
(
codec
,
WM8960_LDAC
,
reg
|
0x100
);
reg
=
snd_soc
_read
(
codec
,
WM8960_RDAC
);
snd_soc
_write
(
codec
,
WM8960_RDAC
,
reg
|
0x100
);
reg
=
snd_soc
_read
(
codec
,
WM8960_LOUT1
);
snd_soc
_write
(
codec
,
WM8960_LOUT1
,
reg
|
0x100
);
reg
=
snd_soc
_read
(
codec
,
WM8960_ROUT1
);
snd_soc
_write
(
codec
,
WM8960_ROUT1
,
reg
|
0x100
);
reg
=
snd_soc
_read
(
codec
,
WM8960_LOUT2
);
snd_soc
_write
(
codec
,
WM8960_LOUT2
,
reg
|
0x100
);
reg
=
snd_soc
_read
(
codec
,
WM8960_ROUT2
);
snd_soc
_write
(
codec
,
WM8960_ROUT2
,
reg
|
0x100
);
wm8960_codec
=
codec
;
...
...
@@ -916,14 +867,13 @@ static __devinit int wm8960_i2c_probe(struct i2c_client *i2c,
return
-
ENOMEM
;
codec
=
&
wm8960
->
codec
;
codec
->
hw_write
=
(
hw_write_t
)
i2c_master_send
;
i2c_set_clientdata
(
i2c
,
wm8960
);
codec
->
control_data
=
i2c
;
codec
->
dev
=
&
i2c
->
dev
;
return
wm8960_register
(
wm8960
);
return
wm8960_register
(
wm8960
,
SND_SOC_I2C
);
}
static
__devexit
int
wm8960_i2c_remove
(
struct
i2c_client
*
client
)
...
...
sound/soc/codecs/wm8961.c
View file @
06cddefc
...
...
@@ -292,9 +292,10 @@ struct wm8961_priv {
u16
reg_cache
[
WM8961_MAX_REGISTER
];
};
static
int
wm8961_
reg_is_volatile
(
int
reg
)
static
int
wm8961_
volatile_register
(
unsigned
int
reg
)
{
switch
(
reg
)
{
case
WM8961_SOFTWARE_RESET
:
case
WM8961_WRITE_SEQUENCER_7
:
case
WM8961_DC_SERVO_1
:
return
1
;
...
...
@@ -304,76 +305,9 @@ static int wm8961_reg_is_volatile(int reg)
}
}
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
);
return
snd_soc
_write
(
codec
,
WM8961_SOFTWARE_RESET
,
0
);
}
/*
...
...
@@ -384,33 +318,33 @@ 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
);
u16
hp_reg
=
snd_soc
_read
(
codec
,
WM8961_ANALOGUE_HP_0
);
u16
cp_reg
=
snd_soc
_read
(
codec
,
WM8961_CHARGE_PUMP_1
);
u16
pwr_reg
=
snd_soc
_read
(
codec
,
WM8961_PWR_MGMT_2
);
u16
dcs_reg
=
snd_soc
_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
);
snd_soc
_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
);
snd_soc
_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
);
snd_soc
_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
);
snd_soc
_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
);
snd_soc
_write
(
codec
,
WM8961_ANALOGUE_HP_0
,
hp_reg
);
/* Enable the DC servo & trigger startup */
dcs_reg
|=
...
...
@@ -418,10 +352,10 @@ static int wm8961_hp_event(struct snd_soc_dapm_widget *w,
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
);
snd_soc
_write
(
codec
,
WM8961_DC_SERVO_1
,
dcs_reg
);
do
{
msleep
(
1
);
dcs_reg
=
wm8961
_read
(
codec
,
WM8961_DC_SERVO_1
);
dcs_reg
=
snd_soc
_read
(
codec
,
WM8961_DC_SERVO_1
);
}
while
(
--
timeout
&&
dcs_reg
&
(
WM8961_DCS_TRIG_STARTUP_HPR
|
WM8961_DCS_TRIG_STARTUP_HPL
));
...
...
@@ -433,39 +367,39 @@ static int wm8961_hp_event(struct snd_soc_dapm_widget *w,
/* Enable the output stage */
hp_reg
|=
WM8961_HPR_ENA_OUTP
|
WM8961_HPL_ENA_OUTP
;
wm8961
_write
(
codec
,
WM8961_ANALOGUE_HP_0
,
hp_reg
);
snd_soc
_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
);
snd_soc
_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
);
snd_soc
_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
);
snd_soc
_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
);
snd_soc
_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
);
snd_soc
_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
);
snd_soc
_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
,
snd_soc
_write
(
codec
,
WM8961_CHARGE_PUMP_1
,
cp_reg
&
~
WM8961_CP_ENA
);
}
...
...
@@ -476,27 +410,27 @@ 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
);
u16
pwr_reg
=
snd_soc
_read
(
codec
,
WM8961_PWR_MGMT_2
);
u16
spk_reg
=
snd_soc
_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
);
snd_soc
_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
);
snd_soc
_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
);
snd_soc
_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
);
snd_soc
_write
(
codec
,
WM8961_PWR_MGMT_2
,
pwr_reg
);
}
return
0
;
...
...
@@ -714,10 +648,10 @@ static int wm8961_hw_params(struct snd_pcm_substream *substream,
abs
(
wm8961_srate
[
best
].
rate
-
fs
))
best
=
i
;
}
reg
=
wm8961
_read
(
codec
,
WM8961_ADDITIONAL_CONTROL_3
);
reg
=
snd_soc
_read
(
codec
,
WM8961_ADDITIONAL_CONTROL_3
);
reg
&=
~
WM8961_SAMPLE_RATE_MASK
;
reg
|=
wm8961_srate
[
best
].
val
;
wm8961
_write
(
codec
,
WM8961_ADDITIONAL_CONTROL_3
,
reg
);
snd_soc
_write
(
codec
,
WM8961_ADDITIONAL_CONTROL_3
,
reg
);
dev_dbg
(
codec
->
dev
,
"Selected SRATE %dHz for %dHz
\n
"
,
wm8961_srate
[
best
].
rate
,
fs
);
...
...
@@ -747,12 +681,12 @@ static int wm8961_hw_params(struct snd_pcm_substream *substream,
wm8961_clk_sys_ratio
[
i
].
ratio
,
wm8961
->
sysclk
,
fs
,
wm8961
->
sysclk
/
fs
);
reg
=
wm8961
_read
(
codec
,
WM8961_CLOCKING_4
);
reg
=
snd_soc
_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
);
snd_soc
_write
(
codec
,
WM8961_CLOCKING_4
,
reg
);
reg
=
wm8961
_read
(
codec
,
WM8961_AUDIO_INTERFACE_0
);
reg
=
snd_soc
_read
(
codec
,
WM8961_AUDIO_INTERFACE_0
);
reg
&=
~
WM8961_WL_MASK
;
switch
(
params_format
(
params
))
{
case
SNDRV_PCM_FORMAT_S16_LE
:
...
...
@@ -769,15 +703,15 @@ static int wm8961_hw_params(struct snd_pcm_substream *substream,
default:
return
-
EINVAL
;
}
wm8961
_write
(
codec
,
WM8961_AUDIO_INTERFACE_0
,
reg
);
snd_soc
_write
(
codec
,
WM8961_AUDIO_INTERFACE_0
,
reg
);
/* Sloping stop-band filter is recommended for <= 24kHz */
reg
=
wm8961
_read
(
codec
,
WM8961_ADC_DAC_CONTROL_2
);
reg
=
snd_soc
_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
);
snd_soc
_write
(
codec
,
WM8961_ADC_DAC_CONTROL_2
,
reg
);
return
0
;
}
...
...
@@ -788,7 +722,7 @@ static int wm8961_set_sysclk(struct snd_soc_dai *dai, int clk_id,
{
struct
snd_soc_codec
*
codec
=
dai
->
codec
;
struct
wm8961_priv
*
wm8961
=
codec
->
private_data
;
u16
reg
=
wm8961
_read
(
codec
,
WM8961_CLOCKING1
);
u16
reg
=
snd_soc
_read
(
codec
,
WM8961_CLOCKING1
);
if
(
freq
>
33000000
)
{
dev_err
(
codec
->
dev
,
"MCLK must be <33MHz
\n
"
);
...
...
@@ -804,7 +738,7 @@ static int wm8961_set_sysclk(struct snd_soc_dai *dai, int clk_id,
reg
&=
WM8961_MCLKDIV
;
}
wm8961
_write
(
codec
,
WM8961_CLOCKING1
,
reg
);
snd_soc
_write
(
codec
,
WM8961_CLOCKING1
,
reg
);
wm8961
->
sysclk
=
freq
;
...
...
@@ -814,7 +748,7 @@ static int wm8961_set_sysclk(struct snd_soc_dai *dai, int clk_id,
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
);
u16
aif
=
snd_soc
_read
(
codec
,
WM8961_AUDIO_INTERFACE_0
);
aif
&=
~
(
WM8961_BCLKINV
|
WM8961_LRP
|
WM8961_MS
|
WM8961_FORMAT_MASK
);
...
...
@@ -874,26 +808,26 @@ static int wm8961_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
return
-
EINVAL
;
}
return
wm8961
_write
(
codec
,
WM8961_AUDIO_INTERFACE_0
,
aif
);
return
snd_soc
_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
);
u16
reg
=
snd_soc
_read
(
codec
,
WM8961_ADDITIONAL_CONTROL_2
);
if
(
tristate
)
reg
|=
WM8961_TRIS
;
else
reg
&=
~
WM8961_TRIS
;
return
wm8961
_write
(
codec
,
WM8961_ADDITIONAL_CONTROL_2
,
reg
);
return
snd_soc
_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
);
u16
reg
=
snd_soc
_read
(
codec
,
WM8961_ADC_DAC_CONTROL_1
);
if
(
mute
)
reg
|=
WM8961_DACMU
;
...
...
@@ -902,7 +836,7 @@ static int wm8961_digital_mute(struct snd_soc_dai *dai, int mute)
msleep
(
17
);
return
wm8961
_write
(
codec
,
WM8961_ADC_DAC_CONTROL_1
,
reg
);
return
snd_soc
_write
(
codec
,
WM8961_ADC_DAC_CONTROL_1
,
reg
);
}
static
int
wm8961_set_clkdiv
(
struct
snd_soc_dai
*
dai
,
int
div_id
,
int
div
)
...
...
@@ -912,17 +846,17 @@ static int wm8961_set_clkdiv(struct snd_soc_dai *dai, int div_id, int div)
switch
(
div_id
)
{
case
WM8961_BCLK
:
reg
=
wm8961
_read
(
codec
,
WM8961_CLOCKING2
);
reg
=
snd_soc
_read
(
codec
,
WM8961_CLOCKING2
);
reg
&=
~
WM8961_BCLKDIV_MASK
;
reg
|=
div
;
wm8961
_write
(
codec
,
WM8961_CLOCKING2
,
reg
);
snd_soc
_write
(
codec
,
WM8961_CLOCKING2
,
reg
);
break
;
case
WM8961_LRCLK
:
reg
=
wm8961
_read
(
codec
,
WM8961_AUDIO_INTERFACE_2
);
reg
=
snd_soc
_read
(
codec
,
WM8961_AUDIO_INTERFACE_2
);
reg
&=
~
WM8961_LRCLK_RATE_MASK
;
reg
|=
div
;
wm8961
_write
(
codec
,
WM8961_AUDIO_INTERFACE_2
,
reg
);
snd_soc
_write
(
codec
,
WM8961_AUDIO_INTERFACE_2
,
reg
);
break
;
default:
...
...
@@ -949,34 +883,34 @@ static int wm8961_set_bias_level(struct snd_soc_codec *codec,
case
SND_SOC_BIAS_PREPARE
:
if
(
codec
->
bias_level
==
SND_SOC_BIAS_STANDBY
)
{
/* Enable bias generation */
reg
=
wm8961
_read
(
codec
,
WM8961_ANTI_POP
);
reg
=
snd_soc
_read
(
codec
,
WM8961_ANTI_POP
);
reg
|=
WM8961_BUFIOEN
|
WM8961_BUFDCOPEN
;
wm8961
_write
(
codec
,
WM8961_ANTI_POP
,
reg
);
snd_soc
_write
(
codec
,
WM8961_ANTI_POP
,
reg
);
/* VMID=2*50k, VREF */
reg
=
wm8961
_read
(
codec
,
WM8961_PWR_MGMT_1
);
reg
=
snd_soc
_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
);
snd_soc
_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
=
snd_soc
_read
(
codec
,
WM8961_PWR_MGMT_1
);
reg
&=
~
WM8961_VREF
;
wm8961
_write
(
codec
,
WM8961_PWR_MGMT_1
,
reg
);
snd_soc
_write
(
codec
,
WM8961_PWR_MGMT_1
,
reg
);
/* Bias generation off */
reg
=
wm8961
_read
(
codec
,
WM8961_ANTI_POP
);
reg
=
snd_soc
_read
(
codec
,
WM8961_ANTI_POP
);
reg
&=
~
(
WM8961_BUFIOEN
|
WM8961_BUFDCOPEN
);
wm8961
_write
(
codec
,
WM8961_ANTI_POP
,
reg
);
snd_soc
_write
(
codec
,
WM8961_ANTI_POP
,
reg
);
/* VMID off */
reg
=
wm8961
_read
(
codec
,
WM8961_PWR_MGMT_1
);
reg
=
snd_soc
_read
(
codec
,
WM8961_PWR_MGMT_1
);
reg
&=
~
WM8961_VMIDSEL_MASK
;
wm8961
_write
(
codec
,
WM8961_PWR_MGMT_1
,
reg
);
snd_soc
_write
(
codec
,
WM8961_PWR_MGMT_1
,
reg
);
}
break
;
...
...
@@ -1101,7 +1035,7 @@ static int wm8961_resume(struct platform_device *pdev)
if
(
i
==
WM8961_SOFTWARE_RESET
)
continue
;
wm8961
_write
(
codec
,
i
,
reg_cache
[
i
]);
snd_soc
_write
(
codec
,
i
,
reg_cache
[
i
]);
}
wm8961_set_bias_level
(
codec
,
SND_SOC_BIAS_STANDBY
);
...
...
@@ -1140,26 +1074,32 @@ static int wm8961_register(struct wm8961_priv *wm8961)
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
;
codec
->
volatile_register
=
wm8961_volatile_register
;
memcpy
(
codec
->
reg_cache
,
wm8961_reg_defaults
,
sizeof
(
wm8961_reg_defaults
));
reg
=
wm8961_read_hw
(
codec
,
WM8961_SOFTWARE_RESET
);
ret
=
snd_soc_codec_set_cache_io
(
codec
,
8
,
16
,
SND_SOC_I2C
);
if
(
ret
!=
0
)
{
dev_err
(
codec
->
dev
,
"Failed to set cache I/O: %d
\n
"
,
ret
);
goto
err
;
}
reg
=
snd_soc_read
(
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
);
/* This isn't volatile - readback doesn't correspond to write */
reg
=
codec
->
hw_read
(
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
)
...
...
@@ -1172,37 +1112,37 @@ static int wm8961_register(struct wm8961_priv *wm8961)
}
/* Enable class W */
reg
=
wm8961
_read
(
codec
,
WM8961_CHARGE_PUMP_B
);
reg
=
snd_soc
_read
(
codec
,
WM8961_CHARGE_PUMP_B
);
reg
|=
WM8961_CP_DYN_PWR_MASK
;
wm8961
_write
(
codec
,
WM8961_CHARGE_PUMP_B
,
reg
);
snd_soc
_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
=
snd_soc
_read
(
codec
,
WM8961_ROUT1_VOLUME
);
snd_soc
_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
,
snd_soc
_write
(
codec
,
WM8961_LOUT1_VOLUME
,
reg
|
WM8961_LO1ZC
);
reg
=
snd_soc
_read
(
codec
,
WM8961_ROUT2_VOLUME
);
snd_soc
_write
(
codec
,
WM8961_ROUT2_VOLUME
,
reg
|
WM8961_SPKRZC
|
WM8961_SPKVU
);
wm8961
_write
(
codec
,
WM8961_LOUT2_VOLUME
,
reg
|
WM8961_SPKLZC
);
snd_soc
_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
);
reg
=
snd_soc
_read
(
codec
,
WM8961_RIGHT_ADC_VOLUME
);
snd_soc
_write
(
codec
,
WM8961_RIGHT_ADC_VOLUME
,
reg
|
WM8961_ADCVU
);
reg
=
snd_soc
_read
(
codec
,
WM8961_RIGHT_INPUT_VOLUME
);
snd_soc
_write
(
codec
,
WM8961_RIGHT_INPUT_VOLUME
,
reg
|
WM8961_IPVU
);
/* Use soft mute by default */
reg
=
wm8961
_read
(
codec
,
WM8961_ADC_DAC_CONTROL_2
);
reg
=
snd_soc
_read
(
codec
,
WM8961_ADC_DAC_CONTROL_2
);
reg
|=
WM8961_DACSMM
;
wm8961
_write
(
codec
,
WM8961_ADC_DAC_CONTROL_2
,
reg
);
snd_soc
_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
=
snd_soc
_read
(
codec
,
WM8961_CLOCKING_3
);
reg
&=
~
WM8961_MANUAL_MODE
;
wm8961
_write
(
codec
,
WM8961_CLOCKING_3
,
reg
);
snd_soc
_write
(
codec
,
WM8961_CLOCKING_3
,
reg
);
wm8961_set_bias_level
(
codec
,
SND_SOC_BIAS_STANDBY
);
...
...
@@ -1250,7 +1190,6 @@ static __devinit int wm8961_i2c_probe(struct i2c_client *i2c,
return
-
ENOMEM
;
codec
=
&
wm8961
->
codec
;
codec
->
hw_write
=
(
hw_write_t
)
i2c_master_send
;
i2c_set_clientdata
(
i2c
,
wm8961
);
codec
->
control_data
=
i2c
;
...
...
sound/soc/codecs/wm8971.c
View file @
06cddefc
...
...
@@ -59,44 +59,7 @@ static const u16 wm8971_reg[] = {
0x0079
,
0x0079
,
0x0079
,
/* 40 */
};
static
inline
unsigned
int
wm8971_read_reg_cache
(
struct
snd_soc_codec
*
codec
,
unsigned
int
reg
)
{
u16
*
cache
=
codec
->
reg_cache
;
if
(
reg
<
WM8971_REG_COUNT
)
return
cache
[
reg
];
return
-
1
;
}
static
inline
void
wm8971_write_reg_cache
(
struct
snd_soc_codec
*
codec
,
unsigned
int
reg
,
unsigned
int
value
)
{
u16
*
cache
=
codec
->
reg_cache
;
if
(
reg
<
WM8971_REG_COUNT
)
cache
[
reg
]
=
value
;
}
static
int
wm8971_write
(
struct
snd_soc_codec
*
codec
,
unsigned
int
reg
,
unsigned
int
value
)
{
u8
data
[
2
];
/* data is
* D15..D9 WM8753 register offset
* D8...D0 register data
*/
data
[
0
]
=
(
reg
<<
1
)
|
((
value
>>
8
)
&
0x0001
);
data
[
1
]
=
value
&
0x00ff
;
wm8971_write_reg_cache
(
codec
,
reg
,
value
);
if
(
codec
->
hw_write
(
codec
->
control_data
,
data
,
2
)
==
2
)
return
0
;
else
return
-
EIO
;
}
#define wm8971_reset(c) wm8971_write(c, WM8971_RESET, 0)
#define wm8971_reset(c) snd_soc_write(c, WM8971_RESET, 0)
/* WM8971 Controls */
static
const
char
*
wm8971_bass
[]
=
{
"Linear Control"
,
"Adaptive Boost"
};
...
...
@@ -521,7 +484,7 @@ static int wm8971_set_dai_fmt(struct snd_soc_dai *codec_dai,
return
-
EINVAL
;
}
wm8971
_write
(
codec
,
WM8971_IFACE
,
iface
);
snd_soc
_write
(
codec
,
WM8971_IFACE
,
iface
);
return
0
;
}
...
...
@@ -533,8 +496,8 @@ static int wm8971_pcm_hw_params(struct snd_pcm_substream *substream,
struct
snd_soc_device
*
socdev
=
rtd
->
socdev
;
struct
snd_soc_codec
*
codec
=
socdev
->
card
->
codec
;
struct
wm8971_priv
*
wm8971
=
codec
->
private_data
;
u16
iface
=
wm8971_read_reg_cache
(
codec
,
WM8971_IFACE
)
&
0x1f3
;
u16
srate
=
wm8971_read_reg_cache
(
codec
,
WM8971_SRATE
)
&
0x1c0
;
u16
iface
=
snd_soc_read
(
codec
,
WM8971_IFACE
)
&
0x1f3
;
u16
srate
=
snd_soc_read
(
codec
,
WM8971_SRATE
)
&
0x1c0
;
int
coeff
=
get_coeff
(
wm8971
->
sysclk
,
params_rate
(
params
));
/* bit size */
...
...
@@ -553,9 +516,9 @@ static int wm8971_pcm_hw_params(struct snd_pcm_substream *substream,
}
/* set iface & srate */
wm8971
_write
(
codec
,
WM8971_IFACE
,
iface
);
snd_soc
_write
(
codec
,
WM8971_IFACE
,
iface
);
if
(
coeff
>=
0
)
wm8971
_write
(
codec
,
WM8971_SRATE
,
srate
|
snd_soc
_write
(
codec
,
WM8971_SRATE
,
srate
|
(
coeff_div
[
coeff
].
sr
<<
1
)
|
coeff_div
[
coeff
].
usb
);
return
0
;
...
...
@@ -564,33 +527,33 @@ static int wm8971_pcm_hw_params(struct snd_pcm_substream *substream,
static
int
wm8971_mute
(
struct
snd_soc_dai
*
dai
,
int
mute
)
{
struct
snd_soc_codec
*
codec
=
dai
->
codec
;
u16
mute_reg
=
wm8971_read_reg_cache
(
codec
,
WM8971_ADCDAC
)
&
0xfff7
;
u16
mute_reg
=
snd_soc_read
(
codec
,
WM8971_ADCDAC
)
&
0xfff7
;
if
(
mute
)
wm8971
_write
(
codec
,
WM8971_ADCDAC
,
mute_reg
|
0x8
);
snd_soc
_write
(
codec
,
WM8971_ADCDAC
,
mute_reg
|
0x8
);
else
wm8971
_write
(
codec
,
WM8971_ADCDAC
,
mute_reg
);
snd_soc
_write
(
codec
,
WM8971_ADCDAC
,
mute_reg
);
return
0
;
}
static
int
wm8971_set_bias_level
(
struct
snd_soc_codec
*
codec
,
enum
snd_soc_bias_level
level
)
{
u16
pwr_reg
=
wm8971_read_reg_cache
(
codec
,
WM8971_PWR1
)
&
0xfe3e
;
u16
pwr_reg
=
snd_soc_read
(
codec
,
WM8971_PWR1
)
&
0xfe3e
;
switch
(
level
)
{
case
SND_SOC_BIAS_ON
:
/* set vmid to 50k and unmute dac */
wm8971
_write
(
codec
,
WM8971_PWR1
,
pwr_reg
|
0x00c1
);
snd_soc
_write
(
codec
,
WM8971_PWR1
,
pwr_reg
|
0x00c1
);
break
;
case
SND_SOC_BIAS_PREPARE
:
break
;
case
SND_SOC_BIAS_STANDBY
:
/* mute dac and set vmid to 500k, enable VREF */
wm8971
_write
(
codec
,
WM8971_PWR1
,
pwr_reg
|
0x0140
);
snd_soc
_write
(
codec
,
WM8971_PWR1
,
pwr_reg
|
0x0140
);
break
;
case
SND_SOC_BIAS_OFF
:
wm8971
_write
(
codec
,
WM8971_PWR1
,
0x0001
);
snd_soc
_write
(
codec
,
WM8971_PWR1
,
0x0001
);
break
;
}
codec
->
bias_level
=
level
;
...
...
@@ -667,8 +630,8 @@ static int wm8971_resume(struct platform_device *pdev)
/* charge wm8971 caps */
if
(
codec
->
suspend_bias_level
==
SND_SOC_BIAS_ON
)
{
reg
=
wm8971_read_reg_cache
(
codec
,
WM8971_PWR1
)
&
0xfe3e
;
wm8971
_write
(
codec
,
WM8971_PWR1
,
reg
|
0x01c0
);
reg
=
snd_soc_read
(
codec
,
WM8971_PWR1
)
&
0xfe3e
;
snd_soc
_write
(
codec
,
WM8971_PWR1
,
reg
|
0x01c0
);
codec
->
bias_level
=
SND_SOC_BIAS_ON
;
queue_delayed_work
(
wm8971_workq
,
&
codec
->
delayed_work
,
msecs_to_jiffies
(
1000
));
...
...
@@ -677,15 +640,14 @@ static int wm8971_resume(struct platform_device *pdev)
return
0
;
}
static
int
wm8971_init
(
struct
snd_soc_device
*
socdev
)
static
int
wm8971_init
(
struct
snd_soc_device
*
socdev
,
enum
snd_soc_control_type
control
)
{
struct
snd_soc_codec
*
codec
=
socdev
->
card
->
codec
;
int
reg
,
ret
=
0
;
codec
->
name
=
"WM8971"
;
codec
->
owner
=
THIS_MODULE
;
codec
->
read
=
wm8971_read_reg_cache
;
codec
->
write
=
wm8971_write
;
codec
->
set_bias_level
=
wm8971_set_bias_level
;
codec
->
dai
=
&
wm8971_dai
;
codec
->
reg_cache_size
=
ARRAY_SIZE
(
wm8971_reg
);
...
...
@@ -695,42 +657,48 @@ static int wm8971_init(struct snd_soc_device *socdev)
if
(
codec
->
reg_cache
==
NULL
)
return
-
ENOMEM
;
ret
=
snd_soc_codec_set_cache_io
(
codec
,
7
,
9
,
control
);
if
(
ret
<
0
)
{
printk
(
KERN_ERR
"wm8971: failed to set cache I/O: %d
\n
"
,
ret
);
goto
err
;
}
wm8971_reset
(
codec
);
/* register pcms */
ret
=
snd_soc_new_pcms
(
socdev
,
SNDRV_DEFAULT_IDX1
,
SNDRV_DEFAULT_STR1
);
if
(
ret
<
0
)
{
printk
(
KERN_ERR
"wm8971: failed to create pcms
\n
"
);
goto
pcm_
err
;
goto
err
;
}
/* charge output caps - set vmid to 5k for quick power up */
reg
=
wm8971_read_reg_cache
(
codec
,
WM8971_PWR1
)
&
0xfe3e
;
wm8971
_write
(
codec
,
WM8971_PWR1
,
reg
|
0x01c0
);
reg
=
snd_soc_read
(
codec
,
WM8971_PWR1
)
&
0xfe3e
;
snd_soc
_write
(
codec
,
WM8971_PWR1
,
reg
|
0x01c0
);
codec
->
bias_level
=
SND_SOC_BIAS_STANDBY
;
queue_delayed_work
(
wm8971_workq
,
&
codec
->
delayed_work
,
msecs_to_jiffies
(
1000
));
/* set the update bits */
reg
=
wm8971_read_reg_cache
(
codec
,
WM8971_LDAC
);
wm8971
_write
(
codec
,
WM8971_LDAC
,
reg
|
0x0100
);
reg
=
wm8971_read_reg_cache
(
codec
,
WM8971_RDAC
);
wm8971
_write
(
codec
,
WM8971_RDAC
,
reg
|
0x0100
);
reg
=
wm8971_read_reg_cache
(
codec
,
WM8971_LOUT1V
);
wm8971
_write
(
codec
,
WM8971_LOUT1V
,
reg
|
0x0100
);
reg
=
wm8971_read_reg_cache
(
codec
,
WM8971_ROUT1V
);
wm8971
_write
(
codec
,
WM8971_ROUT1V
,
reg
|
0x0100
);
reg
=
wm8971_read_reg_cache
(
codec
,
WM8971_LOUT2V
);
wm8971
_write
(
codec
,
WM8971_LOUT2V
,
reg
|
0x0100
);
reg
=
wm8971_read_reg_cache
(
codec
,
WM8971_ROUT2V
);
wm8971
_write
(
codec
,
WM8971_ROUT2V
,
reg
|
0x0100
);
reg
=
wm8971_read_reg_cache
(
codec
,
WM8971_LINVOL
);
wm8971
_write
(
codec
,
WM8971_LINVOL
,
reg
|
0x0100
);
reg
=
wm8971_read_reg_cache
(
codec
,
WM8971_RINVOL
);
wm8971
_write
(
codec
,
WM8971_RINVOL
,
reg
|
0x0100
);
reg
=
snd_soc_read
(
codec
,
WM8971_LDAC
);
snd_soc
_write
(
codec
,
WM8971_LDAC
,
reg
|
0x0100
);
reg
=
snd_soc_read
(
codec
,
WM8971_RDAC
);
snd_soc
_write
(
codec
,
WM8971_RDAC
,
reg
|
0x0100
);
reg
=
snd_soc_read
(
codec
,
WM8971_LOUT1V
);
snd_soc
_write
(
codec
,
WM8971_LOUT1V
,
reg
|
0x0100
);
reg
=
snd_soc_read
(
codec
,
WM8971_ROUT1V
);
snd_soc
_write
(
codec
,
WM8971_ROUT1V
,
reg
|
0x0100
);
reg
=
snd_soc_read
(
codec
,
WM8971_LOUT2V
);
snd_soc
_write
(
codec
,
WM8971_LOUT2V
,
reg
|
0x0100
);
reg
=
snd_soc_read
(
codec
,
WM8971_ROUT2V
);
snd_soc
_write
(
codec
,
WM8971_ROUT2V
,
reg
|
0x0100
);
reg
=
snd_soc_read
(
codec
,
WM8971_LINVOL
);
snd_soc
_write
(
codec
,
WM8971_LINVOL
,
reg
|
0x0100
);
reg
=
snd_soc_read
(
codec
,
WM8971_RINVOL
);
snd_soc
_write
(
codec
,
WM8971_RINVOL
,
reg
|
0x0100
);
snd_soc_add_controls
(
codec
,
wm8971_snd_controls
,
ARRAY_SIZE
(
wm8971_snd_controls
));
...
...
@@ -745,7 +713,7 @@ static int wm8971_init(struct snd_soc_device *socdev)
card_err:
snd_soc_free_pcms
(
socdev
);
snd_soc_dapm_free
(
socdev
);
pcm_
err:
err:
kfree
(
codec
->
reg_cache
);
return
ret
;
}
...
...
@@ -767,7 +735,7 @@ static int wm8971_i2c_probe(struct i2c_client *i2c,
codec
->
control_data
=
i2c
;
ret
=
wm8971_init
(
socdev
);
ret
=
wm8971_init
(
socdev
,
SND_SOC_I2C
);
if
(
ret
<
0
)
pr_err
(
"failed to initialise WM8971
\n
"
);
...
...
@@ -877,7 +845,6 @@ static int wm8971_probe(struct platform_device *pdev)
#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
if
(
setup
->
i2c_address
)
{
codec
->
hw_write
=
(
hw_write_t
)
i2c_master_send
;
ret
=
wm8971_add_i2c_device
(
pdev
,
setup
);
}
#endif
...
...
sound/soc/codecs/wm8988.c
View file @
06cddefc
...
...
@@ -57,50 +57,7 @@ struct wm8988_priv {
};
/*
* read wm8988 register cache
*/
static
inline
unsigned
int
wm8988_read_reg_cache
(
struct
snd_soc_codec
*
codec
,
unsigned
int
reg
)
{
u16
*
cache
=
codec
->
reg_cache
;
if
(
reg
>
WM8988_NUM_REG
)
return
-
1
;
return
cache
[
reg
];
}
/*
* write wm8988 register cache
*/
static
inline
void
wm8988_write_reg_cache
(
struct
snd_soc_codec
*
codec
,
unsigned
int
reg
,
unsigned
int
value
)
{
u16
*
cache
=
codec
->
reg_cache
;
if
(
reg
>
WM8988_NUM_REG
)
return
;
cache
[
reg
]
=
value
;
}
static
int
wm8988_write
(
struct
snd_soc_codec
*
codec
,
unsigned
int
reg
,
unsigned
int
value
)
{
u8
data
[
2
];
/* data is
* D15..D9 WM8753 register offset
* D8...D0 register data
*/
data
[
0
]
=
(
reg
<<
1
)
|
((
value
>>
8
)
&
0x0001
);
data
[
1
]
=
value
&
0x00ff
;
wm8988_write_reg_cache
(
codec
,
reg
,
value
);
if
(
codec
->
hw_write
(
codec
->
control_data
,
data
,
2
)
==
2
)
return
0
;
else
return
-
EIO
;
}
#define wm8988_reset(c) wm8988_write(c, WM8988_RESET, 0)
#define wm8988_reset(c) snd_soc_write(c, WM8988_RESET, 0)
/*
* WM8988 Controls
...
...
@@ -226,15 +183,15 @@ static int wm8988_lrc_control(struct snd_soc_dapm_widget *w,
struct
snd_kcontrol
*
kcontrol
,
int
event
)
{
struct
snd_soc_codec
*
codec
=
w
->
codec
;
u16
adctl2
=
wm8988_read_reg_cache
(
codec
,
WM8988_ADCTL2
);
u16
adctl2
=
snd_soc_read
(
codec
,
WM8988_ADCTL2
);
/* Use the DAC to gate LRC if active, otherwise use ADC */
if
(
wm8988_read_reg_cache
(
codec
,
WM8988_PWR2
)
&
0x180
)
if
(
snd_soc_read
(
codec
,
WM8988_PWR2
)
&
0x180
)
adctl2
&=
~
0x4
;
else
adctl2
|=
0x4
;
return
wm8988
_write
(
codec
,
WM8988_ADCTL2
,
adctl2
);
return
snd_soc
_write
(
codec
,
WM8988_ADCTL2
,
adctl2
);
}
static
const
char
*
wm8988_line_texts
[]
=
{
...
...
@@ -619,7 +576,7 @@ static int wm8988_set_dai_fmt(struct snd_soc_dai *codec_dai,
return
-
EINVAL
;
}
wm8988
_write
(
codec
,
WM8988_IFACE
,
iface
);
snd_soc
_write
(
codec
,
WM8988_IFACE
,
iface
);
return
0
;
}
...
...
@@ -653,8 +610,8 @@ static int wm8988_pcm_hw_params(struct snd_pcm_substream *substream,
struct
snd_soc_device
*
socdev
=
rtd
->
socdev
;
struct
snd_soc_codec
*
codec
=
socdev
->
card
->
codec
;
struct
wm8988_priv
*
wm8988
=
codec
->
private_data
;
u16
iface
=
wm8988_read_reg_cache
(
codec
,
WM8988_IFACE
)
&
0x1f3
;
u16
srate
=
wm8988_read_reg_cache
(
codec
,
WM8988_SRATE
)
&
0x180
;
u16
iface
=
snd_soc_read
(
codec
,
WM8988_IFACE
)
&
0x1f3
;
u16
srate
=
snd_soc_read
(
codec
,
WM8988_SRATE
)
&
0x180
;
int
coeff
;
coeff
=
get_coeff
(
wm8988
->
sysclk
,
params_rate
(
params
));
...
...
@@ -685,9 +642,9 @@ static int wm8988_pcm_hw_params(struct snd_pcm_substream *substream,
}
/* set iface & srate */
wm8988
_write
(
codec
,
WM8988_IFACE
,
iface
);
snd_soc
_write
(
codec
,
WM8988_IFACE
,
iface
);
if
(
coeff
>=
0
)
wm8988
_write
(
codec
,
WM8988_SRATE
,
srate
|
snd_soc
_write
(
codec
,
WM8988_SRATE
,
srate
|
(
coeff_div
[
coeff
].
sr
<<
1
)
|
coeff_div
[
coeff
].
usb
);
return
0
;
...
...
@@ -696,19 +653,19 @@ static int wm8988_pcm_hw_params(struct snd_pcm_substream *substream,
static
int
wm8988_mute
(
struct
snd_soc_dai
*
dai
,
int
mute
)
{
struct
snd_soc_codec
*
codec
=
dai
->
codec
;
u16
mute_reg
=
wm8988_read_reg_cache
(
codec
,
WM8988_ADCDAC
)
&
0xfff7
;
u16
mute_reg
=
snd_soc_read
(
codec
,
WM8988_ADCDAC
)
&
0xfff7
;
if
(
mute
)
wm8988
_write
(
codec
,
WM8988_ADCDAC
,
mute_reg
|
0x8
);
snd_soc
_write
(
codec
,
WM8988_ADCDAC
,
mute_reg
|
0x8
);
else
wm8988
_write
(
codec
,
WM8988_ADCDAC
,
mute_reg
);
snd_soc
_write
(
codec
,
WM8988_ADCDAC
,
mute_reg
);
return
0
;
}
static
int
wm8988_set_bias_level
(
struct
snd_soc_codec
*
codec
,
enum
snd_soc_bias_level
level
)
{
u16
pwr_reg
=
wm8988_read_reg_cache
(
codec
,
WM8988_PWR1
)
&
~
0x1c1
;
u16
pwr_reg
=
snd_soc_read
(
codec
,
WM8988_PWR1
)
&
~
0x1c1
;
switch
(
level
)
{
case
SND_SOC_BIAS_ON
:
...
...
@@ -716,24 +673,24 @@ static int wm8988_set_bias_level(struct snd_soc_codec *codec,
case
SND_SOC_BIAS_PREPARE
:
/* VREF, VMID=2x50k, digital enabled */
wm8988
_write
(
codec
,
WM8988_PWR1
,
pwr_reg
|
0x00c0
);
snd_soc
_write
(
codec
,
WM8988_PWR1
,
pwr_reg
|
0x00c0
);
break
;
case
SND_SOC_BIAS_STANDBY
:
if
(
codec
->
bias_level
==
SND_SOC_BIAS_OFF
)
{
/* VREF, VMID=2x5k */
wm8988
_write
(
codec
,
WM8988_PWR1
,
pwr_reg
|
0x1c1
);
snd_soc
_write
(
codec
,
WM8988_PWR1
,
pwr_reg
|
0x1c1
);
/* Charge caps */
msleep
(
100
);
}
/* VREF, VMID=2*500k, digital stopped */
wm8988
_write
(
codec
,
WM8988_PWR1
,
pwr_reg
|
0x0141
);
snd_soc
_write
(
codec
,
WM8988_PWR1
,
pwr_reg
|
0x0141
);
break
;
case
SND_SOC_BIAS_OFF
:
wm8988
_write
(
codec
,
WM8988_PWR1
,
0x0000
);
snd_soc
_write
(
codec
,
WM8988_PWR1
,
0x0000
);
break
;
}
codec
->
bias_level
=
level
;
...
...
@@ -868,7 +825,8 @@ struct snd_soc_codec_device soc_codec_dev_wm8988 = {
};
EXPORT_SYMBOL_GPL
(
soc_codec_dev_wm8988
);
static
int
wm8988_register
(
struct
wm8988_priv
*
wm8988
)
static
int
wm8988_register
(
struct
wm8988_priv
*
wm8988
,
enum
snd_soc_control_type
control
)
{
struct
snd_soc_codec
*
codec
=
&
wm8988
->
codec
;
int
ret
;
...
...
@@ -887,8 +845,6 @@ static int wm8988_register(struct wm8988_priv *wm8988)
codec
->
private_data
=
wm8988
;
codec
->
name
=
"WM8988"
;
codec
->
owner
=
THIS_MODULE
;
codec
->
read
=
wm8988_read_reg_cache
;
codec
->
write
=
wm8988_write
;
codec
->
dai
=
&
wm8988_dai
;
codec
->
num_dai
=
1
;
codec
->
reg_cache_size
=
ARRAY_SIZE
(
wm8988
->
reg_cache
);
...
...
@@ -899,6 +855,12 @@ static int wm8988_register(struct wm8988_priv *wm8988)
memcpy
(
codec
->
reg_cache
,
wm8988_reg
,
sizeof
(
wm8988_reg
));
ret
=
snd_soc_codec_set_cache_io
(
codec
,
7
,
9
,
control
);
if
(
ret
<
0
)
{
dev_err
(
codec
->
dev
,
"Failed to set cache I/O: %d
\n
"
,
ret
);
goto
err
;
}
ret
=
wm8988_reset
(
codec
);
if
(
ret
<
0
)
{
dev_err
(
codec
->
dev
,
"Failed to issue reset
\n
"
);
...
...
@@ -906,16 +868,16 @@ static int wm8988_register(struct wm8988_priv *wm8988)
}
/* set the update bits (we always update left then right) */
reg
=
wm8988_read_reg_cache
(
codec
,
WM8988_RADC
);
wm8988
_write
(
codec
,
WM8988_RADC
,
reg
|
0x100
);
reg
=
wm8988_read_reg_cache
(
codec
,
WM8988_RDAC
);
wm8988
_write
(
codec
,
WM8988_RDAC
,
reg
|
0x0100
);
reg
=
wm8988_read_reg_cache
(
codec
,
WM8988_ROUT1V
);
wm8988
_write
(
codec
,
WM8988_ROUT1V
,
reg
|
0x0100
);
reg
=
wm8988_read_reg_cache
(
codec
,
WM8988_ROUT2V
);
wm8988
_write
(
codec
,
WM8988_ROUT2V
,
reg
|
0x0100
);
reg
=
wm8988_read_reg_cache
(
codec
,
WM8988_RINVOL
);
wm8988
_write
(
codec
,
WM8988_RINVOL
,
reg
|
0x0100
);
reg
=
snd_soc_read
(
codec
,
WM8988_RADC
);
snd_soc
_write
(
codec
,
WM8988_RADC
,
reg
|
0x100
);
reg
=
snd_soc_read
(
codec
,
WM8988_RDAC
);
snd_soc
_write
(
codec
,
WM8988_RDAC
,
reg
|
0x0100
);
reg
=
snd_soc_read
(
codec
,
WM8988_ROUT1V
);
snd_soc
_write
(
codec
,
WM8988_ROUT1V
,
reg
|
0x0100
);
reg
=
snd_soc_read
(
codec
,
WM8988_ROUT2V
);
snd_soc
_write
(
codec
,
WM8988_ROUT2V
,
reg
|
0x0100
);
reg
=
snd_soc_read
(
codec
,
WM8988_RINVOL
);
snd_soc
_write
(
codec
,
WM8988_RINVOL
,
reg
|
0x0100
);
wm8988_set_bias_level
(
&
wm8988
->
codec
,
SND_SOC_BIAS_STANDBY
);
...
...
@@ -966,14 +928,13 @@ static int wm8988_i2c_probe(struct i2c_client *i2c,
return
-
ENOMEM
;
codec
=
&
wm8988
->
codec
;
codec
->
hw_write
=
(
hw_write_t
)
i2c_master_send
;
i2c_set_clientdata
(
i2c
,
wm8988
);
codec
->
control_data
=
i2c
;
codec
->
dev
=
&
i2c
->
dev
;
return
wm8988_register
(
wm8988
);
return
wm8988_register
(
wm8988
,
SND_SOC_I2C
);
}
static
int
wm8988_i2c_remove
(
struct
i2c_client
*
client
)
...
...
@@ -1018,30 +979,6 @@ static struct i2c_driver wm8988_i2c_driver = {
#endif
#if defined(CONFIG_SPI_MASTER)
static
int
wm8988_spi_write
(
struct
spi_device
*
spi
,
const
char
*
data
,
int
len
)
{
struct
spi_transfer
t
;
struct
spi_message
m
;
u8
msg
[
2
];
if
(
len
<=
0
)
return
0
;
msg
[
0
]
=
data
[
0
];
msg
[
1
]
=
data
[
1
];
spi_message_init
(
&
m
);
memset
(
&
t
,
0
,
(
sizeof
t
));
t
.
tx_buf
=
&
msg
[
0
];
t
.
len
=
len
;
spi_message_add_tail
(
&
t
,
&
m
);
spi_sync
(
spi
,
&
m
);
return
len
;
}
static
int
__devinit
wm8988_spi_probe
(
struct
spi_device
*
spi
)
{
struct
wm8988_priv
*
wm8988
;
...
...
@@ -1052,13 +989,12 @@ static int __devinit wm8988_spi_probe(struct spi_device *spi)
return
-
ENOMEM
;
codec
=
&
wm8988
->
codec
;
codec
->
hw_write
=
(
hw_write_t
)
wm8988_spi_write
;
codec
->
control_data
=
spi
;
codec
->
dev
=
&
spi
->
dev
;
spi
->
dev
.
driver_data
=
wm8988
;
return
wm8988_register
(
wm8988
);
return
wm8988_register
(
wm8988
,
SND_SOC_SPI
);
}
static
int
__devexit
wm8988_spi_remove
(
struct
spi_device
*
spi
)
...
...
sound/soc/codecs/wm8990.c
View file @
06cddefc
...
...
@@ -108,53 +108,7 @@ static const u16 wm8990_reg[] = {
0x0000
,
/* R63 - Driver internal */
};
/*
* read wm8990 register cache
*/
static
inline
unsigned
int
wm8990_read_reg_cache
(
struct
snd_soc_codec
*
codec
,
unsigned
int
reg
)
{
u16
*
cache
=
codec
->
reg_cache
;
BUG_ON
(
reg
>=
ARRAY_SIZE
(
wm8990_reg
));
return
cache
[
reg
];
}
/*
* write wm8990 register cache
*/
static
inline
void
wm8990_write_reg_cache
(
struct
snd_soc_codec
*
codec
,
unsigned
int
reg
,
unsigned
int
value
)
{
u16
*
cache
=
codec
->
reg_cache
;
/* Reset register and reserved registers are uncached */
if
(
reg
==
0
||
reg
>=
ARRAY_SIZE
(
wm8990_reg
))
return
;
cache
[
reg
]
=
value
;
}
/*
* write to the wm8990 register space
*/
static
int
wm8990_write
(
struct
snd_soc_codec
*
codec
,
unsigned
int
reg
,
unsigned
int
value
)
{
u8
data
[
3
];
data
[
0
]
=
reg
&
0xFF
;
data
[
1
]
=
(
value
>>
8
)
&
0xFF
;
data
[
2
]
=
value
&
0xFF
;
wm8990_write_reg_cache
(
codec
,
reg
,
value
);
if
(
codec
->
hw_write
(
codec
->
control_data
,
data
,
3
)
==
2
)
return
0
;
else
return
-
EIO
;
}
#define wm8990_reset(c) wm8990_write(c, WM8990_RESET, 0)
#define wm8990_reset(c) snd_soc_write(c, WM8990_RESET, 0)
static
const
DECLARE_TLV_DB_LINEAR
(
rec_mix_tlv
,
-
1500
,
600
);
...
...
@@ -187,8 +141,8 @@ static int wm899x_outpga_put_volsw_vu(struct snd_kcontrol *kcontrol,
return
ret
;
/* now hit the volume update bits (always bit 8) */
val
=
wm8990_read_reg_cache
(
codec
,
reg
);
return
wm8990
_write
(
codec
,
reg
,
val
|
0x0100
);
val
=
snd_soc_read
(
codec
,
reg
);
return
snd_soc
_write
(
codec
,
reg
,
val
|
0x0100
);
}
#define SOC_WM899X_OUTPGA_SINGLE_R_TLV(xname, reg, shift, max, invert,\
...
...
@@ -427,8 +381,8 @@ static int inmixer_event(struct snd_soc_dapm_widget *w,
{
u16
reg
,
fakepower
;
reg
=
wm8990_read_reg_cache
(
w
->
codec
,
WM8990_POWER_MANAGEMENT_2
);
fakepower
=
wm8990_read_reg_cache
(
w
->
codec
,
WM8990_INTDRIVBITS
);
reg
=
snd_soc_read
(
w
->
codec
,
WM8990_POWER_MANAGEMENT_2
);
fakepower
=
snd_soc_read
(
w
->
codec
,
WM8990_INTDRIVBITS
);
if
(
fakepower
&
((
1
<<
WM8990_INMIXL_PWR_BIT
)
|
(
1
<<
WM8990_AINLMUX_PWR_BIT
)))
{
...
...
@@ -443,7 +397,7 @@ static int inmixer_event(struct snd_soc_dapm_widget *w,
}
else
{
reg
&=
~
WM8990_AINL_ENA
;
}
wm8990
_write
(
w
->
codec
,
WM8990_POWER_MANAGEMENT_2
,
reg
);
snd_soc
_write
(
w
->
codec
,
WM8990_POWER_MANAGEMENT_2
,
reg
);
return
0
;
}
...
...
@@ -457,7 +411,7 @@ static int outmixer_event(struct snd_soc_dapm_widget *w,
switch
(
reg_shift
)
{
case
WM8990_SPEAKER_MIXER
|
(
WM8990_LDSPK_BIT
<<
8
)
:
reg
=
wm8990_read_reg_cache
(
w
->
codec
,
WM8990_OUTPUT_MIXER1
);
reg
=
snd_soc_read
(
w
->
codec
,
WM8990_OUTPUT_MIXER1
);
if
(
reg
&
WM8990_LDLO
)
{
printk
(
KERN_WARNING
"Cannot set as Output Mixer 1 LDLO Set
\n
"
);
...
...
@@ -465,7 +419,7 @@ static int outmixer_event(struct snd_soc_dapm_widget *w,
}
break
;
case
WM8990_SPEAKER_MIXER
|
(
WM8990_RDSPK_BIT
<<
8
):
reg
=
wm8990_read_reg_cache
(
w
->
codec
,
WM8990_OUTPUT_MIXER2
);
reg
=
snd_soc_read
(
w
->
codec
,
WM8990_OUTPUT_MIXER2
);
if
(
reg
&
WM8990_RDRO
)
{
printk
(
KERN_WARNING
"Cannot set as Output Mixer 2 RDRO Set
\n
"
);
...
...
@@ -473,7 +427,7 @@ static int outmixer_event(struct snd_soc_dapm_widget *w,
}
break
;
case
WM8990_OUTPUT_MIXER1
|
(
WM8990_LDLO_BIT
<<
8
):
reg
=
wm8990_read_reg_cache
(
w
->
codec
,
WM8990_SPEAKER_MIXER
);
reg
=
snd_soc_read
(
w
->
codec
,
WM8990_SPEAKER_MIXER
);
if
(
reg
&
WM8990_LDSPK
)
{
printk
(
KERN_WARNING
"Cannot set as Speaker Mixer LDSPK Set
\n
"
);
...
...
@@ -481,7 +435,7 @@ static int outmixer_event(struct snd_soc_dapm_widget *w,
}
break
;
case
WM8990_OUTPUT_MIXER2
|
(
WM8990_RDRO_BIT
<<
8
):
reg
=
wm8990_read_reg_cache
(
w
->
codec
,
WM8990_SPEAKER_MIXER
);
reg
=
snd_soc_read
(
w
->
codec
,
WM8990_SPEAKER_MIXER
);
if
(
reg
&
WM8990_RDSPK
)
{
printk
(
KERN_WARNING
"Cannot set as Speaker Mixer RDSPK Set
\n
"
);
...
...
@@ -1029,24 +983,24 @@ static int wm8990_set_dai_pll(struct snd_soc_dai *codec_dai,
pll_factors
(
&
pll_div
,
freq_out
*
4
,
freq_in
);
/* Turn on PLL */
reg
=
wm8990_read_reg_cache
(
codec
,
WM8990_POWER_MANAGEMENT_2
);
reg
=
snd_soc_read
(
codec
,
WM8990_POWER_MANAGEMENT_2
);
reg
|=
WM8990_PLL_ENA
;
wm8990
_write
(
codec
,
WM8990_POWER_MANAGEMENT_2
,
reg
);
snd_soc
_write
(
codec
,
WM8990_POWER_MANAGEMENT_2
,
reg
);
/* sysclk comes from PLL */
reg
=
wm8990_read_reg_cache
(
codec
,
WM8990_CLOCKING_2
);
wm8990
_write
(
codec
,
WM8990_CLOCKING_2
,
reg
|
WM8990_SYSCLK_SRC
);
reg
=
snd_soc_read
(
codec
,
WM8990_CLOCKING_2
);
snd_soc
_write
(
codec
,
WM8990_CLOCKING_2
,
reg
|
WM8990_SYSCLK_SRC
);
/* set up N , fractional mode and pre-divisor if neccessary */
wm8990
_write
(
codec
,
WM8990_PLL1
,
pll_div
.
n
|
WM8990_SDM
|
snd_soc
_write
(
codec
,
WM8990_PLL1
,
pll_div
.
n
|
WM8990_SDM
|
(
pll_div
.
div2
?
WM8990_PRESCALE
:
0
));
wm8990
_write
(
codec
,
WM8990_PLL2
,
(
u8
)(
pll_div
.
k
>>
8
));
wm8990
_write
(
codec
,
WM8990_PLL3
,
(
u8
)(
pll_div
.
k
&
0xFF
));
snd_soc
_write
(
codec
,
WM8990_PLL2
,
(
u8
)(
pll_div
.
k
>>
8
));
snd_soc
_write
(
codec
,
WM8990_PLL3
,
(
u8
)(
pll_div
.
k
&
0xFF
));
}
else
{
/* Turn on PLL */
reg
=
wm8990_read_reg_cache
(
codec
,
WM8990_POWER_MANAGEMENT_2
);
reg
=
snd_soc_read
(
codec
,
WM8990_POWER_MANAGEMENT_2
);
reg
&=
~
WM8990_PLL_ENA
;
wm8990
_write
(
codec
,
WM8990_POWER_MANAGEMENT_2
,
reg
);
snd_soc
_write
(
codec
,
WM8990_POWER_MANAGEMENT_2
,
reg
);
}
return
0
;
}
...
...
@@ -1073,8 +1027,8 @@ static int wm8990_set_dai_fmt(struct snd_soc_dai *codec_dai,
struct
snd_soc_codec
*
codec
=
codec_dai
->
codec
;
u16
audio1
,
audio3
;
audio1
=
wm8990_read_reg_cache
(
codec
,
WM8990_AUDIO_INTERFACE_1
);
audio3
=
wm8990_read_reg_cache
(
codec
,
WM8990_AUDIO_INTERFACE_3
);
audio1
=
snd_soc_read
(
codec
,
WM8990_AUDIO_INTERFACE_1
);
audio3
=
snd_soc_read
(
codec
,
WM8990_AUDIO_INTERFACE_3
);
/* set master/slave audio interface */
switch
(
fmt
&
SND_SOC_DAIFMT_MASTER_MASK
)
{
...
...
@@ -1115,8 +1069,8 @@ static int wm8990_set_dai_fmt(struct snd_soc_dai *codec_dai,
return
-
EINVAL
;
}
wm8990
_write
(
codec
,
WM8990_AUDIO_INTERFACE_1
,
audio1
);
wm8990
_write
(
codec
,
WM8990_AUDIO_INTERFACE_3
,
audio3
);
snd_soc
_write
(
codec
,
WM8990_AUDIO_INTERFACE_1
,
audio1
);
snd_soc
_write
(
codec
,
WM8990_AUDIO_INTERFACE_3
,
audio3
);
return
0
;
}
...
...
@@ -1128,24 +1082,24 @@ static int wm8990_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
switch
(
div_id
)
{
case
WM8990_MCLK_DIV
:
reg
=
wm8990_read_reg_cache
(
codec
,
WM8990_CLOCKING_2
)
&
reg
=
snd_soc_read
(
codec
,
WM8990_CLOCKING_2
)
&
~
WM8990_MCLK_DIV_MASK
;
wm8990
_write
(
codec
,
WM8990_CLOCKING_2
,
reg
|
div
);
snd_soc
_write
(
codec
,
WM8990_CLOCKING_2
,
reg
|
div
);
break
;
case
WM8990_DACCLK_DIV
:
reg
=
wm8990_read_reg_cache
(
codec
,
WM8990_CLOCKING_2
)
&
reg
=
snd_soc_read
(
codec
,
WM8990_CLOCKING_2
)
&
~
WM8990_DAC_CLKDIV_MASK
;
wm8990
_write
(
codec
,
WM8990_CLOCKING_2
,
reg
|
div
);
snd_soc
_write
(
codec
,
WM8990_CLOCKING_2
,
reg
|
div
);
break
;
case
WM8990_ADCCLK_DIV
:
reg
=
wm8990_read_reg_cache
(
codec
,
WM8990_CLOCKING_2
)
&
reg
=
snd_soc_read
(
codec
,
WM8990_CLOCKING_2
)
&
~
WM8990_ADC_CLKDIV_MASK
;
wm8990
_write
(
codec
,
WM8990_CLOCKING_2
,
reg
|
div
);
snd_soc
_write
(
codec
,
WM8990_CLOCKING_2
,
reg
|
div
);
break
;
case
WM8990_BCLK_DIV
:
reg
=
wm8990_read_reg_cache
(
codec
,
WM8990_CLOCKING_1
)
&
reg
=
snd_soc_read
(
codec
,
WM8990_CLOCKING_1
)
&
~
WM8990_BCLK_DIV_MASK
;
wm8990
_write
(
codec
,
WM8990_CLOCKING_1
,
reg
|
div
);
snd_soc
_write
(
codec
,
WM8990_CLOCKING_1
,
reg
|
div
);
break
;
default:
return
-
EINVAL
;
...
...
@@ -1164,7 +1118,7 @@ static int wm8990_hw_params(struct snd_pcm_substream *substream,
struct
snd_soc_pcm_runtime
*
rtd
=
substream
->
private_data
;
struct
snd_soc_device
*
socdev
=
rtd
->
socdev
;
struct
snd_soc_codec
*
codec
=
socdev
->
card
->
codec
;
u16
audio1
=
wm8990_read_reg_cache
(
codec
,
WM8990_AUDIO_INTERFACE_1
);
u16
audio1
=
snd_soc_read
(
codec
,
WM8990_AUDIO_INTERFACE_1
);
audio1
&=
~
WM8990_AIF_WL_MASK
;
/* bit size */
...
...
@@ -1182,7 +1136,7 @@ static int wm8990_hw_params(struct snd_pcm_substream *substream,
break
;
}
wm8990
_write
(
codec
,
WM8990_AUDIO_INTERFACE_1
,
audio1
);
snd_soc
_write
(
codec
,
WM8990_AUDIO_INTERFACE_1
,
audio1
);
return
0
;
}
...
...
@@ -1191,12 +1145,12 @@ static int wm8990_mute(struct snd_soc_dai *dai, int mute)
struct
snd_soc_codec
*
codec
=
dai
->
codec
;
u16
val
;
val
=
wm8990_read_reg_cache
(
codec
,
WM8990_DAC_CTRL
)
&
~
WM8990_DAC_MUTE
;
val
=
snd_soc_read
(
codec
,
WM8990_DAC_CTRL
)
&
~
WM8990_DAC_MUTE
;
if
(
mute
)
wm8990
_write
(
codec
,
WM8990_DAC_CTRL
,
val
|
WM8990_DAC_MUTE
);
snd_soc
_write
(
codec
,
WM8990_DAC_CTRL
,
val
|
WM8990_DAC_MUTE
);
else
wm8990
_write
(
codec
,
WM8990_DAC_CTRL
,
val
);
snd_soc
_write
(
codec
,
WM8990_DAC_CTRL
,
val
);
return
0
;
}
...
...
@@ -1212,21 +1166,21 @@ static int wm8990_set_bias_level(struct snd_soc_codec *codec,
case
SND_SOC_BIAS_PREPARE
:
/* VMID=2*50k */
val
=
wm8990_read_reg_cache
(
codec
,
WM8990_POWER_MANAGEMENT_1
)
&
val
=
snd_soc_read
(
codec
,
WM8990_POWER_MANAGEMENT_1
)
&
~
WM8990_VMID_MODE_MASK
;
wm8990
_write
(
codec
,
WM8990_POWER_MANAGEMENT_1
,
val
|
0x2
);
snd_soc
_write
(
codec
,
WM8990_POWER_MANAGEMENT_1
,
val
|
0x2
);
break
;
case
SND_SOC_BIAS_STANDBY
:
if
(
codec
->
bias_level
==
SND_SOC_BIAS_OFF
)
{
/* Enable all output discharge bits */
wm8990
_write
(
codec
,
WM8990_ANTIPOP1
,
WM8990_DIS_LLINE
|
snd_soc
_write
(
codec
,
WM8990_ANTIPOP1
,
WM8990_DIS_LLINE
|
WM8990_DIS_RLINE
|
WM8990_DIS_OUT3
|
WM8990_DIS_OUT4
|
WM8990_DIS_LOUT
|
WM8990_DIS_ROUT
);
/* Enable POBCTRL, SOFT_ST, VMIDTOG and BUFDCOPEN */
wm8990
_write
(
codec
,
WM8990_ANTIPOP2
,
WM8990_SOFTST
|
snd_soc
_write
(
codec
,
WM8990_ANTIPOP2
,
WM8990_SOFTST
|
WM8990_BUFDCOPEN
|
WM8990_POBCTRL
|
WM8990_VMIDTOG
);
...
...
@@ -1234,83 +1188,83 @@ static int wm8990_set_bias_level(struct snd_soc_codec *codec,
msleep
(
msecs_to_jiffies
(
300
));
/* Disable VMIDTOG */
wm8990
_write
(
codec
,
WM8990_ANTIPOP2
,
WM8990_SOFTST
|
snd_soc
_write
(
codec
,
WM8990_ANTIPOP2
,
WM8990_SOFTST
|
WM8990_BUFDCOPEN
|
WM8990_POBCTRL
);
/* disable all output discharge bits */
wm8990
_write
(
codec
,
WM8990_ANTIPOP1
,
0
);
snd_soc
_write
(
codec
,
WM8990_ANTIPOP1
,
0
);
/* Enable outputs */
wm8990
_write
(
codec
,
WM8990_POWER_MANAGEMENT_1
,
0x1b00
);
snd_soc
_write
(
codec
,
WM8990_POWER_MANAGEMENT_1
,
0x1b00
);
msleep
(
msecs_to_jiffies
(
50
));
/* Enable VMID at 2x50k */
wm8990
_write
(
codec
,
WM8990_POWER_MANAGEMENT_1
,
0x1f02
);
snd_soc
_write
(
codec
,
WM8990_POWER_MANAGEMENT_1
,
0x1f02
);
msleep
(
msecs_to_jiffies
(
100
));
/* Enable VREF */
wm8990
_write
(
codec
,
WM8990_POWER_MANAGEMENT_1
,
0x1f03
);
snd_soc
_write
(
codec
,
WM8990_POWER_MANAGEMENT_1
,
0x1f03
);
msleep
(
msecs_to_jiffies
(
600
));
/* Enable BUFIOEN */
wm8990
_write
(
codec
,
WM8990_ANTIPOP2
,
WM8990_SOFTST
|
snd_soc
_write
(
codec
,
WM8990_ANTIPOP2
,
WM8990_SOFTST
|
WM8990_BUFDCOPEN
|
WM8990_POBCTRL
|
WM8990_BUFIOEN
);
/* Disable outputs */
wm8990
_write
(
codec
,
WM8990_POWER_MANAGEMENT_1
,
0x3
);
snd_soc
_write
(
codec
,
WM8990_POWER_MANAGEMENT_1
,
0x3
);
/* disable POBCTRL, SOFT_ST and BUFDCOPEN */
wm8990
_write
(
codec
,
WM8990_ANTIPOP2
,
WM8990_BUFIOEN
);
snd_soc
_write
(
codec
,
WM8990_ANTIPOP2
,
WM8990_BUFIOEN
);
/* Enable workaround for ADC clocking issue. */
wm8990
_write
(
codec
,
WM8990_EXT_ACCESS_ENA
,
0x2
);
wm8990
_write
(
codec
,
WM8990_EXT_CTL1
,
0xa003
);
wm8990
_write
(
codec
,
WM8990_EXT_ACCESS_ENA
,
0
);
snd_soc
_write
(
codec
,
WM8990_EXT_ACCESS_ENA
,
0x2
);
snd_soc
_write
(
codec
,
WM8990_EXT_CTL1
,
0xa003
);
snd_soc
_write
(
codec
,
WM8990_EXT_ACCESS_ENA
,
0
);
}
/* VMID=2*250k */
val
=
wm8990_read_reg_cache
(
codec
,
WM8990_POWER_MANAGEMENT_1
)
&
val
=
snd_soc_read
(
codec
,
WM8990_POWER_MANAGEMENT_1
)
&
~
WM8990_VMID_MODE_MASK
;
wm8990
_write
(
codec
,
WM8990_POWER_MANAGEMENT_1
,
val
|
0x4
);
snd_soc
_write
(
codec
,
WM8990_POWER_MANAGEMENT_1
,
val
|
0x4
);
break
;
case
SND_SOC_BIAS_OFF
:
/* Enable POBCTRL and SOFT_ST */
wm8990
_write
(
codec
,
WM8990_ANTIPOP2
,
WM8990_SOFTST
|
snd_soc
_write
(
codec
,
WM8990_ANTIPOP2
,
WM8990_SOFTST
|
WM8990_POBCTRL
|
WM8990_BUFIOEN
);
/* Enable POBCTRL, SOFT_ST and BUFDCOPEN */
wm8990
_write
(
codec
,
WM8990_ANTIPOP2
,
WM8990_SOFTST
|
snd_soc
_write
(
codec
,
WM8990_ANTIPOP2
,
WM8990_SOFTST
|
WM8990_BUFDCOPEN
|
WM8990_POBCTRL
|
WM8990_BUFIOEN
);
/* mute DAC */
val
=
wm8990_read_reg_cache
(
codec
,
WM8990_DAC_CTRL
);
wm8990
_write
(
codec
,
WM8990_DAC_CTRL
,
val
|
WM8990_DAC_MUTE
);
val
=
snd_soc_read
(
codec
,
WM8990_DAC_CTRL
);
snd_soc
_write
(
codec
,
WM8990_DAC_CTRL
,
val
|
WM8990_DAC_MUTE
);
/* Enable any disabled outputs */
wm8990
_write
(
codec
,
WM8990_POWER_MANAGEMENT_1
,
0x1f03
);
snd_soc
_write
(
codec
,
WM8990_POWER_MANAGEMENT_1
,
0x1f03
);
/* Disable VMID */
wm8990
_write
(
codec
,
WM8990_POWER_MANAGEMENT_1
,
0x1f01
);
snd_soc
_write
(
codec
,
WM8990_POWER_MANAGEMENT_1
,
0x1f01
);
msleep
(
msecs_to_jiffies
(
300
));
/* Enable all output discharge bits */
wm8990
_write
(
codec
,
WM8990_ANTIPOP1
,
WM8990_DIS_LLINE
|
snd_soc
_write
(
codec
,
WM8990_ANTIPOP1
,
WM8990_DIS_LLINE
|
WM8990_DIS_RLINE
|
WM8990_DIS_OUT3
|
WM8990_DIS_OUT4
|
WM8990_DIS_LOUT
|
WM8990_DIS_ROUT
);
/* Disable VREF */
wm8990
_write
(
codec
,
WM8990_POWER_MANAGEMENT_1
,
0x0
);
snd_soc
_write
(
codec
,
WM8990_POWER_MANAGEMENT_1
,
0x0
);
/* disable POBCTRL, SOFT_ST and BUFDCOPEN */
wm8990
_write
(
codec
,
WM8990_ANTIPOP2
,
0x0
);
snd_soc
_write
(
codec
,
WM8990_ANTIPOP2
,
0x0
);
break
;
}
...
...
@@ -1411,8 +1365,6 @@ static int wm8990_init(struct snd_soc_device *socdev)
codec
->
name
=
"WM8990"
;
codec
->
owner
=
THIS_MODULE
;
codec
->
read
=
wm8990_read_reg_cache
;
codec
->
write
=
wm8990_write
;
codec
->
set_bias_level
=
wm8990_set_bias_level
;
codec
->
dai
=
&
wm8990_dai
;
codec
->
num_dai
=
2
;
...
...
@@ -1422,6 +1374,12 @@ static int wm8990_init(struct snd_soc_device *socdev)
if
(
codec
->
reg_cache
==
NULL
)
return
-
ENOMEM
;
ret
=
snd_soc_codec_set_cache_io
(
codec
,
8
,
16
,
SND_SOC_I2C
);
if
(
ret
<
0
)
{
printk
(
KERN_ERR
"wm8990: failed to set cache I/O: %d
\n
"
,
ret
);
goto
pcm_err
;
}
wm8990_reset
(
codec
);
/* register pcms */
...
...
@@ -1435,18 +1393,18 @@ static int wm8990_init(struct snd_soc_device *socdev)
codec
->
bias_level
=
SND_SOC_BIAS_OFF
;
wm8990_set_bias_level
(
codec
,
SND_SOC_BIAS_STANDBY
);
reg
=
wm8990_read_reg_cache
(
codec
,
WM8990_AUDIO_INTERFACE_4
);
wm8990
_write
(
codec
,
WM8990_AUDIO_INTERFACE_4
,
reg
|
WM8990_ALRCGPIO1
);
reg
=
snd_soc_read
(
codec
,
WM8990_AUDIO_INTERFACE_4
);
snd_soc
_write
(
codec
,
WM8990_AUDIO_INTERFACE_4
,
reg
|
WM8990_ALRCGPIO1
);
reg
=
wm8990_read_reg_cache
(
codec
,
WM8990_GPIO1_GPIO2
)
&
reg
=
snd_soc_read
(
codec
,
WM8990_GPIO1_GPIO2
)
&
~
WM8990_GPIO1_SEL_MASK
;
wm8990
_write
(
codec
,
WM8990_GPIO1_GPIO2
,
reg
|
1
);
snd_soc
_write
(
codec
,
WM8990_GPIO1_GPIO2
,
reg
|
1
);
reg
=
wm8990_read_reg_cache
(
codec
,
WM8990_POWER_MANAGEMENT_2
);
wm8990
_write
(
codec
,
WM8990_POWER_MANAGEMENT_2
,
reg
|
WM8990_OPCLK_ENA
);
reg
=
snd_soc_read
(
codec
,
WM8990_POWER_MANAGEMENT_2
);
snd_soc
_write
(
codec
,
WM8990_POWER_MANAGEMENT_2
,
reg
|
WM8990_OPCLK_ENA
);
wm8990
_write
(
codec
,
WM8990_LEFT_OUTPUT_VOLUME
,
0x50
|
(
1
<<
8
));
wm8990
_write
(
codec
,
WM8990_RIGHT_OUTPUT_VOLUME
,
0x50
|
(
1
<<
8
));
snd_soc
_write
(
codec
,
WM8990_LEFT_OUTPUT_VOLUME
,
0x50
|
(
1
<<
8
));
snd_soc
_write
(
codec
,
WM8990_RIGHT_OUTPUT_VOLUME
,
0x50
|
(
1
<<
8
));
snd_soc_add_controls
(
codec
,
wm8990_snd_controls
,
ARRAY_SIZE
(
wm8990_snd_controls
));
...
...
sound/soc/codecs/wm9081.c
View file @
06cddefc
...
...
@@ -168,84 +168,19 @@ struct wm9081_priv {
struct
wm9081_retune_mobile_config
*
retune
;
};
static
int
wm9081_
reg_is_volatile
(
int
reg
)
static
int
wm9081_
volatile_register
(
unsigned
int
reg
)
{
switch
(
reg
)
{
case
WM9081_SOFTWARE_RESET
:
return
1
;
default:
return
0
;
}
}
static
unsigned
int
wm9081_read_reg_cache
(
struct
snd_soc_codec
*
codec
,
unsigned
int
reg
)
{
u16
*
cache
=
codec
->
reg_cache
;
BUG_ON
(
reg
>
WM9081_MAX_REGISTER
);
return
cache
[
reg
];
}
static
unsigned
int
wm9081_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
>
WM9081_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
wm9081_read
(
struct
snd_soc_codec
*
codec
,
unsigned
int
reg
)
{
if
(
wm9081_reg_is_volatile
(
reg
))
return
wm9081_read_hw
(
codec
,
reg
);
else
return
wm9081_read_reg_cache
(
codec
,
reg
);
}
static
int
wm9081_write
(
struct
snd_soc_codec
*
codec
,
unsigned
int
reg
,
unsigned
int
value
)
{
u16
*
cache
=
codec
->
reg_cache
;
u8
data
[
3
];
BUG_ON
(
reg
>
WM9081_MAX_REGISTER
);
if
(
!
wm9081_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
wm9081_reset
(
struct
snd_soc_codec
*
codec
)
{
return
wm9081
_write
(
codec
,
WM9081_SOFTWARE_RESET
,
0
);
return
snd_soc
_write
(
codec
,
WM9081_SOFTWARE_RESET
,
0
);
}
static
const
DECLARE_TLV_DB_SCALE
(
drc_in_tlv
,
-
4500
,
75
,
0
);
...
...
@@ -356,7 +291,7 @@ static int speaker_mode_get(struct snd_kcontrol *kcontrol,
struct
snd_soc_codec
*
codec
=
snd_kcontrol_chip
(
kcontrol
);
unsigned
int
reg
;
reg
=
wm9081
_read
(
codec
,
WM9081_ANALOGUE_SPEAKER_2
);
reg
=
snd_soc
_read
(
codec
,
WM9081_ANALOGUE_SPEAKER_2
);
if
(
reg
&
WM9081_SPK_MODE
)
ucontrol
->
value
.
integer
.
value
[
0
]
=
1
;
else
...
...
@@ -375,8 +310,8 @@ static int speaker_mode_put(struct snd_kcontrol *kcontrol,
struct
snd_ctl_elem_value
*
ucontrol
)
{
struct
snd_soc_codec
*
codec
=
snd_kcontrol_chip
(
kcontrol
);
unsigned
int
reg_pwr
=
wm9081
_read
(
codec
,
WM9081_POWER_MANAGEMENT
);
unsigned
int
reg2
=
wm9081
_read
(
codec
,
WM9081_ANALOGUE_SPEAKER_2
);
unsigned
int
reg_pwr
=
snd_soc
_read
(
codec
,
WM9081_POWER_MANAGEMENT
);
unsigned
int
reg2
=
snd_soc
_read
(
codec
,
WM9081_ANALOGUE_SPEAKER_2
);
/* Are we changing anything? */
if
(
ucontrol
->
value
.
integer
.
value
[
0
]
==
...
...
@@ -397,7 +332,7 @@ static int speaker_mode_put(struct snd_kcontrol *kcontrol,
reg2
&=
~
WM9081_SPK_MODE
;
}
wm9081
_write
(
codec
,
WM9081_ANALOGUE_SPEAKER_2
,
reg2
);
snd_soc
_write
(
codec
,
WM9081_ANALOGUE_SPEAKER_2
,
reg2
);
return
0
;
}
...
...
@@ -456,7 +391,7 @@ static int speaker_event(struct snd_soc_dapm_widget *w,
struct
snd_kcontrol
*
kcontrol
,
int
event
)
{
struct
snd_soc_codec
*
codec
=
w
->
codec
;
unsigned
int
reg
=
wm9081
_read
(
codec
,
WM9081_POWER_MANAGEMENT
);
unsigned
int
reg
=
snd_soc
_read
(
codec
,
WM9081_POWER_MANAGEMENT
);
switch
(
event
)
{
case
SND_SOC_DAPM_POST_PMU
:
...
...
@@ -468,7 +403,7 @@ static int speaker_event(struct snd_soc_dapm_widget *w,
break
;
}
wm9081
_write
(
codec
,
WM9081_POWER_MANAGEMENT
,
reg
);
snd_soc
_write
(
codec
,
WM9081_POWER_MANAGEMENT
,
reg
);
return
0
;
}
...
...
@@ -607,7 +542,7 @@ static int wm9081_set_fll(struct snd_soc_codec *codec, int fll_id,
if
(
ret
!=
0
)
return
ret
;
reg5
=
wm9081
_read
(
codec
,
WM9081_FLL_CONTROL_5
);
reg5
=
snd_soc
_read
(
codec
,
WM9081_FLL_CONTROL_5
);
reg5
&=
~
WM9081_FLL_CLK_SRC_MASK
;
switch
(
fll_id
)
{
...
...
@@ -621,44 +556,44 @@ static int wm9081_set_fll(struct snd_soc_codec *codec, int fll_id,
}
/* Disable CLK_SYS while we reconfigure */
clk_sys_reg
=
wm9081
_read
(
codec
,
WM9081_CLOCK_CONTROL_3
);
clk_sys_reg
=
snd_soc
_read
(
codec
,
WM9081_CLOCK_CONTROL_3
);
if
(
clk_sys_reg
&
WM9081_CLK_SYS_ENA
)
wm9081
_write
(
codec
,
WM9081_CLOCK_CONTROL_3
,
snd_soc
_write
(
codec
,
WM9081_CLOCK_CONTROL_3
,
clk_sys_reg
&
~
WM9081_CLK_SYS_ENA
);
/* Any FLL configuration change requires that the FLL be
* disabled first. */
reg1
=
wm9081
_read
(
codec
,
WM9081_FLL_CONTROL_1
);
reg1
=
snd_soc
_read
(
codec
,
WM9081_FLL_CONTROL_1
);
reg1
&=
~
WM9081_FLL_ENA
;
wm9081
_write
(
codec
,
WM9081_FLL_CONTROL_1
,
reg1
);
snd_soc
_write
(
codec
,
WM9081_FLL_CONTROL_1
,
reg1
);
/* Apply the configuration */
if
(
fll_div
.
k
)
reg1
|=
WM9081_FLL_FRAC_MASK
;
else
reg1
&=
~
WM9081_FLL_FRAC_MASK
;
wm9081
_write
(
codec
,
WM9081_FLL_CONTROL_1
,
reg1
);
snd_soc
_write
(
codec
,
WM9081_FLL_CONTROL_1
,
reg1
);
wm9081
_write
(
codec
,
WM9081_FLL_CONTROL_2
,
snd_soc
_write
(
codec
,
WM9081_FLL_CONTROL_2
,
(
fll_div
.
fll_outdiv
<<
WM9081_FLL_OUTDIV_SHIFT
)
|
(
fll_div
.
fll_fratio
<<
WM9081_FLL_FRATIO_SHIFT
));
wm9081
_write
(
codec
,
WM9081_FLL_CONTROL_3
,
fll_div
.
k
);
snd_soc
_write
(
codec
,
WM9081_FLL_CONTROL_3
,
fll_div
.
k
);
reg4
=
wm9081
_read
(
codec
,
WM9081_FLL_CONTROL_4
);
reg4
=
snd_soc
_read
(
codec
,
WM9081_FLL_CONTROL_4
);
reg4
&=
~
WM9081_FLL_N_MASK
;
reg4
|=
fll_div
.
n
<<
WM9081_FLL_N_SHIFT
;
wm9081
_write
(
codec
,
WM9081_FLL_CONTROL_4
,
reg4
);
snd_soc
_write
(
codec
,
WM9081_FLL_CONTROL_4
,
reg4
);
reg5
&=
~
WM9081_FLL_CLK_REF_DIV_MASK
;
reg5
|=
fll_div
.
fll_clk_ref_div
<<
WM9081_FLL_CLK_REF_DIV_SHIFT
;
wm9081
_write
(
codec
,
WM9081_FLL_CONTROL_5
,
reg5
);
snd_soc
_write
(
codec
,
WM9081_FLL_CONTROL_5
,
reg5
);
/* Enable the FLL */
wm9081
_write
(
codec
,
WM9081_FLL_CONTROL_1
,
reg1
|
WM9081_FLL_ENA
);
snd_soc
_write
(
codec
,
WM9081_FLL_CONTROL_1
,
reg1
|
WM9081_FLL_ENA
);
/* Then bring CLK_SYS up again if it was disabled */
if
(
clk_sys_reg
&
WM9081_CLK_SYS_ENA
)
wm9081
_write
(
codec
,
WM9081_CLOCK_CONTROL_3
,
clk_sys_reg
);
snd_soc
_write
(
codec
,
WM9081_CLOCK_CONTROL_3
,
clk_sys_reg
);
dev_dbg
(
codec
->
dev
,
"FLL enabled at %dHz->%dHz
\n
"
,
Fref
,
Fout
);
...
...
@@ -742,19 +677,19 @@ static int configure_clock(struct snd_soc_codec *codec)
return
-
EINVAL
;
}
reg
=
wm9081
_read
(
codec
,
WM9081_CLOCK_CONTROL_1
);
reg
=
snd_soc
_read
(
codec
,
WM9081_CLOCK_CONTROL_1
);
if
(
mclkdiv
)
reg
|=
WM9081_MCLKDIV2
;
else
reg
&=
~
WM9081_MCLKDIV2
;
wm9081
_write
(
codec
,
WM9081_CLOCK_CONTROL_1
,
reg
);
snd_soc
_write
(
codec
,
WM9081_CLOCK_CONTROL_1
,
reg
);
reg
=
wm9081
_read
(
codec
,
WM9081_CLOCK_CONTROL_3
);
reg
=
snd_soc
_read
(
codec
,
WM9081_CLOCK_CONTROL_3
);
if
(
fll
)
reg
|=
WM9081_CLK_SRC_SEL
;
else
reg
&=
~
WM9081_CLK_SRC_SEL
;
wm9081
_write
(
codec
,
WM9081_CLOCK_CONTROL_3
,
reg
);
snd_soc
_write
(
codec
,
WM9081_CLOCK_CONTROL_3
,
reg
);
dev_dbg
(
codec
->
dev
,
"CLK_SYS is %dHz
\n
"
,
wm9081
->
sysclk_rate
);
...
...
@@ -854,76 +789,76 @@ static int wm9081_set_bias_level(struct snd_soc_codec *codec,
case
SND_SOC_BIAS_PREPARE
:
/* VMID=2*40k */
reg
=
wm9081
_read
(
codec
,
WM9081_VMID_CONTROL
);
reg
=
snd_soc
_read
(
codec
,
WM9081_VMID_CONTROL
);
reg
&=
~
WM9081_VMID_SEL_MASK
;
reg
|=
0x2
;
wm9081
_write
(
codec
,
WM9081_VMID_CONTROL
,
reg
);
snd_soc
_write
(
codec
,
WM9081_VMID_CONTROL
,
reg
);
/* Normal bias current */
reg
=
wm9081
_read
(
codec
,
WM9081_BIAS_CONTROL_1
);
reg
=
snd_soc
_read
(
codec
,
WM9081_BIAS_CONTROL_1
);
reg
&=
~
WM9081_STBY_BIAS_ENA
;
wm9081
_write
(
codec
,
WM9081_BIAS_CONTROL_1
,
reg
);
snd_soc
_write
(
codec
,
WM9081_BIAS_CONTROL_1
,
reg
);
break
;
case
SND_SOC_BIAS_STANDBY
:
/* Initial cold start */
if
(
codec
->
bias_level
==
SND_SOC_BIAS_OFF
)
{
/* Disable LINEOUT discharge */
reg
=
wm9081
_read
(
codec
,
WM9081_ANTI_POP_CONTROL
);
reg
=
snd_soc
_read
(
codec
,
WM9081_ANTI_POP_CONTROL
);
reg
&=
~
WM9081_LINEOUT_DISCH
;
wm9081
_write
(
codec
,
WM9081_ANTI_POP_CONTROL
,
reg
);
snd_soc
_write
(
codec
,
WM9081_ANTI_POP_CONTROL
,
reg
);
/* Select startup bias source */
reg
=
wm9081
_read
(
codec
,
WM9081_BIAS_CONTROL_1
);
reg
=
snd_soc
_read
(
codec
,
WM9081_BIAS_CONTROL_1
);
reg
|=
WM9081_BIAS_SRC
|
WM9081_BIAS_ENA
;
wm9081
_write
(
codec
,
WM9081_BIAS_CONTROL_1
,
reg
);
snd_soc
_write
(
codec
,
WM9081_BIAS_CONTROL_1
,
reg
);
/* VMID 2*4k; Soft VMID ramp enable */
reg
=
wm9081
_read
(
codec
,
WM9081_VMID_CONTROL
);
reg
=
snd_soc
_read
(
codec
,
WM9081_VMID_CONTROL
);
reg
|=
WM9081_VMID_RAMP
|
0x6
;
wm9081
_write
(
codec
,
WM9081_VMID_CONTROL
,
reg
);
snd_soc
_write
(
codec
,
WM9081_VMID_CONTROL
,
reg
);
mdelay
(
100
);
/* Normal bias enable & soft start off */
reg
|=
WM9081_BIAS_ENA
;
reg
&=
~
WM9081_VMID_RAMP
;
wm9081
_write
(
codec
,
WM9081_VMID_CONTROL
,
reg
);
snd_soc
_write
(
codec
,
WM9081_VMID_CONTROL
,
reg
);
/* Standard bias source */
reg
=
wm9081
_read
(
codec
,
WM9081_BIAS_CONTROL_1
);
reg
=
snd_soc
_read
(
codec
,
WM9081_BIAS_CONTROL_1
);
reg
&=
~
WM9081_BIAS_SRC
;
wm9081
_write
(
codec
,
WM9081_BIAS_CONTROL_1
,
reg
);
snd_soc
_write
(
codec
,
WM9081_BIAS_CONTROL_1
,
reg
);
}
/* VMID 2*240k */
reg
=
wm9081
_read
(
codec
,
WM9081_BIAS_CONTROL_1
);
reg
=
snd_soc
_read
(
codec
,
WM9081_BIAS_CONTROL_1
);
reg
&=
~
WM9081_VMID_SEL_MASK
;
reg
|=
0x40
;
wm9081
_write
(
codec
,
WM9081_VMID_CONTROL
,
reg
);
snd_soc
_write
(
codec
,
WM9081_VMID_CONTROL
,
reg
);
/* Standby bias current on */
reg
=
wm9081
_read
(
codec
,
WM9081_BIAS_CONTROL_1
);
reg
=
snd_soc
_read
(
codec
,
WM9081_BIAS_CONTROL_1
);
reg
|=
WM9081_STBY_BIAS_ENA
;
wm9081
_write
(
codec
,
WM9081_BIAS_CONTROL_1
,
reg
);
snd_soc
_write
(
codec
,
WM9081_BIAS_CONTROL_1
,
reg
);
break
;
case
SND_SOC_BIAS_OFF
:
/* Startup bias source */
reg
=
wm9081
_read
(
codec
,
WM9081_BIAS_CONTROL_1
);
reg
=
snd_soc
_read
(
codec
,
WM9081_BIAS_CONTROL_1
);
reg
|=
WM9081_BIAS_SRC
;
wm9081
_write
(
codec
,
WM9081_BIAS_CONTROL_1
,
reg
);
snd_soc
_write
(
codec
,
WM9081_BIAS_CONTROL_1
,
reg
);
/* Disable VMID and biases with soft ramping */
reg
=
wm9081
_read
(
codec
,
WM9081_VMID_CONTROL
);
reg
=
snd_soc
_read
(
codec
,
WM9081_VMID_CONTROL
);
reg
&=
~
(
WM9081_VMID_SEL_MASK
|
WM9081_BIAS_ENA
);
reg
|=
WM9081_VMID_RAMP
;
wm9081
_write
(
codec
,
WM9081_VMID_CONTROL
,
reg
);
snd_soc
_write
(
codec
,
WM9081_VMID_CONTROL
,
reg
);
/* Actively discharge LINEOUT */
reg
=
wm9081
_read
(
codec
,
WM9081_ANTI_POP_CONTROL
);
reg
=
snd_soc
_read
(
codec
,
WM9081_ANTI_POP_CONTROL
);
reg
|=
WM9081_LINEOUT_DISCH
;
wm9081
_write
(
codec
,
WM9081_ANTI_POP_CONTROL
,
reg
);
snd_soc
_write
(
codec
,
WM9081_ANTI_POP_CONTROL
,
reg
);
break
;
}
...
...
@@ -937,7 +872,7 @@ static int wm9081_set_dai_fmt(struct snd_soc_dai *dai,
{
struct
snd_soc_codec
*
codec
=
dai
->
codec
;
struct
wm9081_priv
*
wm9081
=
codec
->
private_data
;
unsigned
int
aif2
=
wm9081
_read
(
codec
,
WM9081_AUDIO_INTERFACE_2
);
unsigned
int
aif2
=
snd_soc
_read
(
codec
,
WM9081_AUDIO_INTERFACE_2
);
aif2
&=
~
(
WM9081_AIF_BCLK_INV
|
WM9081_AIF_LRCLK_INV
|
WM9081_BCLK_DIR
|
WM9081_LRCLK_DIR
|
WM9081_AIF_FMT_MASK
);
...
...
@@ -1018,7 +953,7 @@ static int wm9081_set_dai_fmt(struct snd_soc_dai *dai,
return
-
EINVAL
;
}
wm9081
_write
(
codec
,
WM9081_AUDIO_INTERFACE_2
,
aif2
);
snd_soc
_write
(
codec
,
WM9081_AUDIO_INTERFACE_2
,
aif2
);
return
0
;
}
...
...
@@ -1032,18 +967,18 @@ static int wm9081_hw_params(struct snd_pcm_substream *substream,
int
ret
,
i
,
best
,
best_val
,
cur_val
;
unsigned
int
clk_ctrl2
,
aif1
,
aif2
,
aif3
,
aif4
;
clk_ctrl2
=
wm9081
_read
(
codec
,
WM9081_CLOCK_CONTROL_2
);
clk_ctrl2
=
snd_soc
_read
(
codec
,
WM9081_CLOCK_CONTROL_2
);
clk_ctrl2
&=
~
(
WM9081_CLK_SYS_RATE_MASK
|
WM9081_SAMPLE_RATE_MASK
);
aif1
=
wm9081
_read
(
codec
,
WM9081_AUDIO_INTERFACE_1
);
aif1
=
snd_soc
_read
(
codec
,
WM9081_AUDIO_INTERFACE_1
);
aif2
=
wm9081
_read
(
codec
,
WM9081_AUDIO_INTERFACE_2
);
aif2
=
snd_soc
_read
(
codec
,
WM9081_AUDIO_INTERFACE_2
);
aif2
&=
~
WM9081_AIF_WL_MASK
;
aif3
=
wm9081
_read
(
codec
,
WM9081_AUDIO_INTERFACE_3
);
aif3
=
snd_soc
_read
(
codec
,
WM9081_AUDIO_INTERFACE_3
);
aif3
&=
~
WM9081_BCLK_DIV_MASK
;
aif4
=
wm9081
_read
(
codec
,
WM9081_AUDIO_INTERFACE_4
);
aif4
=
snd_soc
_read
(
codec
,
WM9081_AUDIO_INTERFACE_4
);
aif4
&=
~
WM9081_LRCLK_RATE_MASK
;
/* What BCLK do we need? */
...
...
@@ -1157,22 +1092,22 @@ static int wm9081_hw_params(struct snd_pcm_substream *substream,
s
->
name
,
s
->
rate
);
/* If the EQ is enabled then disable it while we write out */
eq1
=
wm9081
_read
(
codec
,
WM9081_EQ_1
)
&
WM9081_EQ_ENA
;
eq1
=
snd_soc
_read
(
codec
,
WM9081_EQ_1
)
&
WM9081_EQ_ENA
;
if
(
eq1
&
WM9081_EQ_ENA
)
wm9081
_write
(
codec
,
WM9081_EQ_1
,
0
);
snd_soc
_write
(
codec
,
WM9081_EQ_1
,
0
);
/* Write out the other values */
for
(
i
=
1
;
i
<
ARRAY_SIZE
(
s
->
config
);
i
++
)
wm9081
_write
(
codec
,
WM9081_EQ_1
+
i
,
s
->
config
[
i
]);
snd_soc
_write
(
codec
,
WM9081_EQ_1
+
i
,
s
->
config
[
i
]);
eq1
|=
(
s
->
config
[
0
]
&
~
WM9081_EQ_ENA
);
wm9081
_write
(
codec
,
WM9081_EQ_1
,
eq1
);
snd_soc
_write
(
codec
,
WM9081_EQ_1
,
eq1
);
}
wm9081
_write
(
codec
,
WM9081_CLOCK_CONTROL_2
,
clk_ctrl2
);
wm9081
_write
(
codec
,
WM9081_AUDIO_INTERFACE_2
,
aif2
);
wm9081
_write
(
codec
,
WM9081_AUDIO_INTERFACE_3
,
aif3
);
wm9081
_write
(
codec
,
WM9081_AUDIO_INTERFACE_4
,
aif4
);
snd_soc
_write
(
codec
,
WM9081_CLOCK_CONTROL_2
,
clk_ctrl2
);
snd_soc
_write
(
codec
,
WM9081_AUDIO_INTERFACE_2
,
aif2
);
snd_soc
_write
(
codec
,
WM9081_AUDIO_INTERFACE_3
,
aif3
);
snd_soc
_write
(
codec
,
WM9081_AUDIO_INTERFACE_4
,
aif4
);
return
0
;
}
...
...
@@ -1182,14 +1117,14 @@ static int wm9081_digital_mute(struct snd_soc_dai *codec_dai, int mute)
struct
snd_soc_codec
*
codec
=
codec_dai
->
codec
;
unsigned
int
reg
;
reg
=
wm9081
_read
(
codec
,
WM9081_DAC_DIGITAL_2
);
reg
=
snd_soc
_read
(
codec
,
WM9081_DAC_DIGITAL_2
);
if
(
mute
)
reg
|=
WM9081_DAC_MUTE
;
else
reg
&=
~
WM9081_DAC_MUTE
;
wm9081
_write
(
codec
,
WM9081_DAC_DIGITAL_2
,
reg
);
snd_soc
_write
(
codec
,
WM9081_DAC_DIGITAL_2
,
reg
);
return
0
;
}
...
...
@@ -1218,7 +1153,7 @@ static int wm9081_set_tdm_slot(struct snd_soc_dai *dai,
unsigned
int
mask
,
int
slots
)
{
struct
snd_soc_codec
*
codec
=
dai
->
codec
;
unsigned
int
aif1
=
wm9081
_read
(
codec
,
WM9081_AUDIO_INTERFACE_1
);
unsigned
int
aif1
=
snd_soc
_read
(
codec
,
WM9081_AUDIO_INTERFACE_1
);
aif1
&=
~
(
WM9081_AIFDAC_TDM_SLOT_MASK
|
WM9081_AIFDAC_TDM_MODE_MASK
);
...
...
@@ -1243,7 +1178,7 @@ static int wm9081_set_tdm_slot(struct snd_soc_dai *dai,
return
-
EINVAL
;
}
wm9081
_write
(
codec
,
WM9081_AUDIO_INTERFACE_1
,
aif1
);
snd_soc
_write
(
codec
,
WM9081_AUDIO_INTERFACE_1
,
aif1
);
return
0
;
}
...
...
@@ -1365,7 +1300,7 @@ static int wm9081_resume(struct platform_device *pdev)
if
(
i
==
WM9081_SOFTWARE_RESET
)
continue
;
wm9081
_write
(
codec
,
i
,
reg_cache
[
i
]);
snd_soc
_write
(
codec
,
i
,
reg_cache
[
i
]);
}
wm9081_set_bias_level
(
codec
,
SND_SOC_BIAS_STANDBY
);
...
...
@@ -1385,7 +1320,8 @@ struct snd_soc_codec_device soc_codec_dev_wm9081 = {
};
EXPORT_SYMBOL_GPL
(
soc_codec_dev_wm9081
);
static
int
wm9081_register
(
struct
wm9081_priv
*
wm9081
)
static
int
wm9081_register
(
struct
wm9081_priv
*
wm9081
,
enum
snd_soc_control_type
control
)
{
struct
snd_soc_codec
*
codec
=
&
wm9081
->
codec
;
int
ret
;
...
...
@@ -1404,19 +1340,24 @@ static int wm9081_register(struct wm9081_priv *wm9081)
codec
->
private_data
=
wm9081
;
codec
->
name
=
"WM9081"
;
codec
->
owner
=
THIS_MODULE
;
codec
->
read
=
wm9081_read
;
codec
->
write
=
wm9081_write
;
codec
->
dai
=
&
wm9081_dai
;
codec
->
num_dai
=
1
;
codec
->
reg_cache_size
=
ARRAY_SIZE
(
wm9081
->
reg_cache
);
codec
->
reg_cache
=
&
wm9081
->
reg_cache
;
codec
->
bias_level
=
SND_SOC_BIAS_OFF
;
codec
->
set_bias_level
=
wm9081_set_bias_level
;
codec
->
volatile_register
=
wm9081_volatile_register
;
memcpy
(
codec
->
reg_cache
,
wm9081_reg_defaults
,
sizeof
(
wm9081_reg_defaults
));
reg
=
wm9081_read_hw
(
codec
,
WM9081_SOFTWARE_RESET
);
ret
=
snd_soc_codec_set_cache_io
(
codec
,
8
,
16
,
control
);
if
(
ret
!=
0
)
{
dev_err
(
codec
->
dev
,
"Failed to set cache I/O: %d
\n
"
,
ret
);
return
ret
;
}
reg
=
snd_soc_read
(
codec
,
WM9081_SOFTWARE_RESET
);
if
(
reg
!=
0x9081
)
{
dev_err
(
codec
->
dev
,
"Device is not a WM9081: ID=0x%x
\n
"
,
reg
);
ret
=
-
EINVAL
;
...
...
@@ -1432,10 +1373,10 @@ static int wm9081_register(struct wm9081_priv *wm9081)
wm9081_set_bias_level
(
codec
,
SND_SOC_BIAS_STANDBY
);
/* Enable zero cross by default */
reg
=
wm9081
_read
(
codec
,
WM9081_ANALOGUE_LINEOUT
);
wm9081
_write
(
codec
,
WM9081_ANALOGUE_LINEOUT
,
reg
|
WM9081_LINEOUTZC
);
reg
=
wm9081
_read
(
codec
,
WM9081_ANALOGUE_SPEAKER_PGA
);
wm9081
_write
(
codec
,
WM9081_ANALOGUE_SPEAKER_PGA
,
reg
=
snd_soc
_read
(
codec
,
WM9081_ANALOGUE_LINEOUT
);
snd_soc
_write
(
codec
,
WM9081_ANALOGUE_LINEOUT
,
reg
|
WM9081_LINEOUTZC
);
reg
=
snd_soc
_read
(
codec
,
WM9081_ANALOGUE_SPEAKER_PGA
);
snd_soc
_write
(
codec
,
WM9081_ANALOGUE_SPEAKER_PGA
,
reg
|
WM9081_SPKPGAZC
);
wm9081_dai
.
dev
=
codec
->
dev
;
...
...
@@ -1490,7 +1431,7 @@ static __devinit int wm9081_i2c_probe(struct i2c_client *i2c,
codec
->
dev
=
&
i2c
->
dev
;
return
wm9081_register
(
wm9081
);
return
wm9081_register
(
wm9081
,
SND_SOC_I2C
);
}
static
__devexit
int
wm9081_i2c_remove
(
struct
i2c_client
*
client
)
...
...
sound/soc/soc-cache.c
0 → 100644
View file @
06cddefc
/*
* soc-cache.c -- ASoC register cache helpers
*
* Copyright 2009 Wolfson Microelectronics PLC.
*
* Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
#include <linux/i2c.h>
#include <linux/spi/spi.h>
#include <sound/soc.h>
static
unsigned
int
snd_soc_7_9_read
(
struct
snd_soc_codec
*
codec
,
unsigned
int
reg
)
{
u16
*
cache
=
codec
->
reg_cache
;
if
(
reg
>=
codec
->
reg_cache_size
)
return
-
1
;
return
cache
[
reg
];
}
static
int
snd_soc_7_9_write
(
struct
snd_soc_codec
*
codec
,
unsigned
int
reg
,
unsigned
int
value
)
{
u16
*
cache
=
codec
->
reg_cache
;
u8
data
[
2
];
int
ret
;
BUG_ON
(
codec
->
volatile_register
);
data
[
0
]
=
(
reg
<<
1
)
|
((
value
>>
8
)
&
0x0001
);
data
[
1
]
=
value
&
0x00ff
;
if
(
reg
<
codec
->
reg_cache_size
)
cache
[
reg
]
=
value
;
ret
=
codec
->
hw_write
(
codec
->
control_data
,
data
,
2
);
if
(
ret
==
2
)
return
0
;
if
(
ret
<
0
)
return
ret
;
else
return
-
EIO
;
}
#if defined(CONFIG_SPI_MASTER)
static
int
snd_soc_7_9_spi_write
(
void
*
control_data
,
const
char
*
data
,
int
len
)
{
struct
spi_device
*
spi
=
control_data
;
struct
spi_transfer
t
;
struct
spi_message
m
;
u8
msg
[
2
];
if
(
len
<=
0
)
return
0
;
msg
[
0
]
=
data
[
0
];
msg
[
1
]
=
data
[
1
];
spi_message_init
(
&
m
);
memset
(
&
t
,
0
,
(
sizeof
t
));
t
.
tx_buf
=
&
msg
[
0
];
t
.
len
=
len
;
spi_message_add_tail
(
&
t
,
&
m
);
spi_sync
(
spi
,
&
m
);
return
len
;
}
#else
#define snd_soc_7_9_spi_write NULL
#endif
static
int
snd_soc_8_16_write
(
struct
snd_soc_codec
*
codec
,
unsigned
int
reg
,
unsigned
int
value
)
{
u16
*
reg_cache
=
codec
->
reg_cache
;
u8
data
[
3
];
data
[
0
]
=
reg
;
data
[
1
]
=
(
value
>>
8
)
&
0xff
;
data
[
2
]
=
value
&
0xff
;
if
(
!
snd_soc_codec_volatile_register
(
codec
,
reg
))
reg_cache
[
reg
]
=
value
;
if
(
codec
->
hw_write
(
codec
->
control_data
,
data
,
3
)
==
3
)
return
0
;
else
return
-
EIO
;
}
static
unsigned
int
snd_soc_8_16_read
(
struct
snd_soc_codec
*
codec
,
unsigned
int
reg
)
{
u16
*
cache
=
codec
->
reg_cache
;
if
(
reg
>=
codec
->
reg_cache_size
||
snd_soc_codec_volatile_register
(
codec
,
reg
))
return
codec
->
hw_read
(
codec
,
reg
);
else
return
cache
[
reg
];
}
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
static
unsigned
int
snd_soc_8_16_read_i2c
(
struct
snd_soc_codec
*
codec
,
unsigned
int
r
)
{
struct
i2c_msg
xfer
[
2
];
u8
reg
=
r
;
u16
data
;
int
ret
;
struct
i2c_client
*
client
=
codec
->
control_data
;
/* 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
);
}
#else
#define snd_soc_8_16_read_i2c NULL
#endif
static
struct
{
int
addr_bits
;
int
data_bits
;
int
(
*
write
)(
struct
snd_soc_codec
*
codec
,
unsigned
int
,
unsigned
int
);
int
(
*
spi_write
)(
void
*
,
const
char
*
,
int
);
unsigned
int
(
*
read
)(
struct
snd_soc_codec
*
,
unsigned
int
);
unsigned
int
(
*
i2c_read
)(
struct
snd_soc_codec
*
,
unsigned
int
);
}
io_types
[]
=
{
{
7
,
9
,
snd_soc_7_9_write
,
snd_soc_7_9_spi_write
,
snd_soc_7_9_read
},
{
8
,
16
,
snd_soc_8_16_write
,
NULL
,
snd_soc_8_16_read
,
snd_soc_8_16_read_i2c
},
};
/**
* snd_soc_codec_set_cache_io: Set up standard I/O functions.
*
* @codec: CODEC to configure.
* @type: Type of cache.
* @addr_bits: Number of bits of register address data.
* @data_bits: Number of bits of data per register.
* @control: Control bus used.
*
* Register formats are frequently shared between many I2C and SPI
* devices. In order to promote code reuse the ASoC core provides
* some standard implementations of CODEC read and write operations
* which can be set up using this function.
*
* The caller is responsible for allocating and initialising the
* actual cache.
*
* Note that at present this code cannot be used by CODECs with
* volatile registers.
*/
int
snd_soc_codec_set_cache_io
(
struct
snd_soc_codec
*
codec
,
int
addr_bits
,
int
data_bits
,
enum
snd_soc_control_type
control
)
{
int
i
;
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
io_types
);
i
++
)
if
(
io_types
[
i
].
addr_bits
==
addr_bits
&&
io_types
[
i
].
data_bits
==
data_bits
)
break
;
if
(
i
==
ARRAY_SIZE
(
io_types
))
{
printk
(
KERN_ERR
"No I/O functions for %d bit address %d bit data
\n
"
,
addr_bits
,
data_bits
);
return
-
EINVAL
;
}
codec
->
write
=
io_types
[
i
].
write
;
codec
->
read
=
io_types
[
i
].
read
;
switch
(
control
)
{
case
SND_SOC_CUSTOM
:
break
;
case
SND_SOC_I2C
:
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
codec
->
hw_write
=
(
hw_write_t
)
i2c_master_send
;
#endif
if
(
io_types
[
i
].
i2c_read
)
codec
->
hw_read
=
io_types
[
i
].
i2c_read
;
break
;
case
SND_SOC_SPI
:
if
(
io_types
[
i
].
spi_write
)
codec
->
hw_write
=
io_types
[
i
].
spi_write
;
break
;
}
return
0
;
}
EXPORT_SYMBOL_GPL
(
snd_soc_codec_set_cache_io
);
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