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
66195b15
Commit
66195b15
authored
Dec 02, 2012
by
Mark Brown
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'asoc/topic/wm8770' into asoc-next
parents
1a9d299d
c6300bb8
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
107 additions
and
110 deletions
+107
-110
sound/soc/codecs/wm8770.c
sound/soc/codecs/wm8770.c
+107
-110
No files found.
sound/soc/codecs/wm8770.c
View file @
66195b15
...
...
@@ -17,6 +17,7 @@
#include <linux/of_device.h>
#include <linux/pm.h>
#include <linux/spi/spi.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
#include <sound/core.h>
...
...
@@ -35,19 +36,52 @@ static const char *wm8770_supply_names[WM8770_NUM_SUPPLIES] = {
"DVDD"
};
static
const
u16
wm8770_reg_defs
[
WM8770_CACHEREGNUM
]
=
{
0x7f
,
0x7f
,
0x7f
,
0x7f
,
0x7f
,
0x7f
,
0x7f
,
0x7f
,
0x7f
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0xff
,
0
,
0x90
,
0
,
0
,
0x22
,
0x22
,
0x3e
,
0xc
,
0xc
,
0x100
,
0x189
,
0x189
,
0x8770
static
const
struct
reg_default
wm8770_reg_defaults
[]
=
{
{
0
,
0x7f
},
{
1
,
0x7f
},
{
2
,
0x7f
},
{
3
,
0x7f
},
{
4
,
0x7f
},
{
5
,
0x7f
},
{
6
,
0x7f
},
{
7
,
0x7f
},
{
8
,
0x7f
},
{
9
,
0xff
},
{
10
,
0xff
},
{
11
,
0xff
},
{
12
,
0xff
},
{
13
,
0xff
},
{
14
,
0xff
},
{
15
,
0xff
},
{
16
,
0xff
},
{
17
,
0xff
},
{
18
,
0
},
{
19
,
0x90
},
{
20
,
0
},
{
21
,
0
},
{
22
,
0x22
},
{
23
,
0x22
},
{
24
,
0x3e
},
{
25
,
0xc
},
{
26
,
0xc
},
{
27
,
0x100
},
{
28
,
0x189
},
{
29
,
0x189
},
{
30
,
0x8770
},
};
static
bool
wm8770_volatile_reg
(
struct
device
*
dev
,
unsigned
int
reg
)
{
switch
(
reg
)
{
case
WM8770_RESET
:
return
true
;
default:
return
false
;
}
}
struct
wm8770_priv
{
enum
snd_soc_control_type
control_type
;
struct
regmap
*
regmap
;
struct
regulator_bulk_data
supplies
[
WM8770_NUM_SUPPLIES
];
struct
notifier_block
disable_nb
[
WM8770_NUM_SUPPLIES
];
struct
snd_soc_codec
*
codec
;
...
...
@@ -71,7 +105,7 @@ static int wm8770_regulator_event_##n(struct notifier_block *nb, \
struct wm8770_priv *wm8770 = container_of(nb, struct wm8770_priv, \
disable_nb[n]); \
if (event & REGULATOR_EVENT_DISABLE) { \
wm8770->codec->cache_sync = 1;
\
regcache_mark_dirty(wm8770->regmap);
\
} \
return 0; \
}
...
...
@@ -466,24 +500,6 @@ static int wm8770_set_sysclk(struct snd_soc_dai *dai,
return
0
;
}
static
void
wm8770_sync_cache
(
struct
snd_soc_codec
*
codec
)
{
int
i
;
u16
*
cache
;
if
(
!
codec
->
cache_sync
)
return
;
codec
->
cache_only
=
0
;
cache
=
codec
->
reg_cache
;
for
(
i
=
0
;
i
<
codec
->
driver
->
reg_cache_size
;
i
++
)
{
if
(
i
==
WM8770_RESET
||
cache
[
i
]
==
wm8770_reg_defs
[
i
])
continue
;
snd_soc_write
(
codec
,
i
,
cache
[
i
]);
}
codec
->
cache_sync
=
0
;
}
static
int
wm8770_set_bias_level
(
struct
snd_soc_codec
*
codec
,
enum
snd_soc_bias_level
level
)
{
...
...
@@ -507,7 +523,9 @@ static int wm8770_set_bias_level(struct snd_soc_codec *codec,
ret
);
return
ret
;
}
wm8770_sync_cache
(
codec
);
regcache_sync
(
wm8770
->
regmap
);
/* global powerup */
snd_soc_write
(
codec
,
WM8770_PWDNCTRL
,
0
);
}
...
...
@@ -554,68 +572,25 @@ static struct snd_soc_dai_driver wm8770_dai = {
.
symmetric_rates
=
1
};
#ifdef CONFIG_PM
static
int
wm8770_suspend
(
struct
snd_soc_codec
*
codec
)
{
wm8770_set_bias_level
(
codec
,
SND_SOC_BIAS_OFF
);
return
0
;
}
static
int
wm8770_resume
(
struct
snd_soc_codec
*
codec
)
{
wm8770_set_bias_level
(
codec
,
SND_SOC_BIAS_STANDBY
);
return
0
;
}
#else
#define wm8770_suspend NULL
#define wm8770_resume NULL
#endif
static
int
wm8770_probe
(
struct
snd_soc_codec
*
codec
)
{
struct
wm8770_priv
*
wm8770
;
int
ret
;
int
i
;
wm8770
=
snd_soc_codec_get_drvdata
(
codec
);
wm8770
->
codec
=
codec
;
ret
=
snd_soc_codec_set_cache_io
(
codec
,
7
,
9
,
wm8770
->
control_type
);
ret
=
snd_soc_codec_set_cache_io
(
codec
,
7
,
9
,
SND_SOC_REGMAP
);
if
(
ret
<
0
)
{
dev_err
(
codec
->
dev
,
"Failed to set cache I/O: %d
\n
"
,
ret
);
return
ret
;
}
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
wm8770
->
supplies
);
i
++
)
wm8770
->
supplies
[
i
].
supply
=
wm8770_supply_names
[
i
];
ret
=
regulator_bulk_get
(
codec
->
dev
,
ARRAY_SIZE
(
wm8770
->
supplies
),
wm8770
->
supplies
);
if
(
ret
)
{
dev_err
(
codec
->
dev
,
"Failed to request supplies: %d
\n
"
,
ret
);
return
ret
;
}
wm8770
->
disable_nb
[
0
].
notifier_call
=
wm8770_regulator_event_0
;
wm8770
->
disable_nb
[
1
].
notifier_call
=
wm8770_regulator_event_1
;
wm8770
->
disable_nb
[
2
].
notifier_call
=
wm8770_regulator_event_2
;
/* This should really be moved into the regulator core */
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
wm8770
->
supplies
);
i
++
)
{
ret
=
regulator_register_notifier
(
wm8770
->
supplies
[
i
].
consumer
,
&
wm8770
->
disable_nb
[
i
]);
if
(
ret
)
{
dev_err
(
codec
->
dev
,
"Failed to register regulator notifier: %d
\n
"
,
ret
);
}
}
ret
=
regulator_bulk_enable
(
ARRAY_SIZE
(
wm8770
->
supplies
),
wm8770
->
supplies
);
if
(
ret
)
{
dev_err
(
codec
->
dev
,
"Failed to enable supplies: %d
\n
"
,
ret
);
goto
err_reg_g
et
;
return
r
et
;
}
ret
=
wm8770_reset
(
codec
);
...
...
@@ -624,8 +599,6 @@ static int wm8770_probe(struct snd_soc_codec *codec)
goto
err_reg_enable
;
}
wm8770_set_bias_level
(
codec
,
SND_SOC_BIAS_STANDBY
);
/* latch the volume update bits */
snd_soc_update_bits
(
codec
,
WM8770_MSDIGVOL
,
0x100
,
0x100
);
snd_soc_update_bits
(
codec
,
WM8770_MSALGVOL
,
0x100
,
0x100
);
...
...
@@ -641,46 +614,22 @@ static int wm8770_probe(struct snd_soc_codec *codec)
/* mute all DACs */
snd_soc_update_bits
(
codec
,
WM8770_DACMUTE
,
0x10
,
0x10
);
snd_soc_add_codec_controls
(
codec
,
wm8770_snd_controls
,
ARRAY_SIZE
(
wm8770_snd_controls
));
snd_soc_dapm_new_controls
(
&
codec
->
dapm
,
wm8770_dapm_widgets
,
ARRAY_SIZE
(
wm8770_dapm_widgets
));
snd_soc_dapm_add_routes
(
&
codec
->
dapm
,
wm8770_intercon
,
ARRAY_SIZE
(
wm8770_intercon
));
return
0
;
err_reg_enable:
regulator_bulk_disable
(
ARRAY_SIZE
(
wm8770
->
supplies
),
wm8770
->
supplies
);
err_reg_get:
regulator_bulk_free
(
ARRAY_SIZE
(
wm8770
->
supplies
),
wm8770
->
supplies
);
return
ret
;
}
static
int
wm8770_remove
(
struct
snd_soc_codec
*
codec
)
{
struct
wm8770_priv
*
wm8770
;
int
i
;
wm8770
=
snd_soc_codec_get_drvdata
(
codec
);
wm8770_set_bias_level
(
codec
,
SND_SOC_BIAS_OFF
);
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
wm8770
->
supplies
);
++
i
)
regulator_unregister_notifier
(
wm8770
->
supplies
[
i
].
consumer
,
&
wm8770
->
disable_nb
[
i
]);
regulator_bulk_free
(
ARRAY_SIZE
(
wm8770
->
supplies
),
wm8770
->
supplies
);
return
0
;
}
static
struct
snd_soc_codec_driver
soc_codec_dev_wm8770
=
{
.
probe
=
wm8770_probe
,
.
remove
=
wm8770_remove
,
.
suspend
=
wm8770_suspend
,
.
resume
=
wm8770_resume
,
.
set_bias_level
=
wm8770_set_bias_level
,
.
idle_bias_off
=
true
,
.
reg_cache_size
=
ARRAY_SIZE
(
wm8770_reg_defs
),
.
reg_word_size
=
sizeof
(
u16
),
.
reg_cache_default
=
wm8770_reg_defs
.
controls
=
wm8770_snd_controls
,
.
num_controls
=
ARRAY_SIZE
(
wm8770_snd_controls
),
.
dapm_widgets
=
wm8770_dapm_widgets
,
.
num_dapm_widgets
=
ARRAY_SIZE
(
wm8770_dapm_widgets
),
.
dapm_routes
=
wm8770_intercon
,
.
num_dapm_routes
=
ARRAY_SIZE
(
wm8770_intercon
),
};
static
const
struct
of_device_id
wm8770_of_match
[]
=
{
...
...
@@ -689,17 +638,57 @@ static const struct of_device_id wm8770_of_match[] = {
};
MODULE_DEVICE_TABLE
(
of
,
wm8770_of_match
);
static
const
struct
regmap_config
wm8770_regmap
=
{
.
reg_bits
=
7
,
.
val_bits
=
9
,
.
max_register
=
WM8770_RESET
,
.
reg_defaults
=
wm8770_reg_defaults
,
.
num_reg_defaults
=
ARRAY_SIZE
(
wm8770_reg_defaults
),
.
cache_type
=
REGCACHE_RBTREE
,
.
volatile_reg
=
wm8770_volatile_reg
,
};
static
int
__devinit
wm8770_spi_probe
(
struct
spi_device
*
spi
)
{
struct
wm8770_priv
*
wm8770
;
int
ret
;
int
ret
,
i
;
wm8770
=
devm_kzalloc
(
&
spi
->
dev
,
sizeof
(
struct
wm8770_priv
),
GFP_KERNEL
);
if
(
!
wm8770
)
return
-
ENOMEM
;
wm8770
->
control_type
=
SND_SOC_SPI
;
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
wm8770
->
supplies
);
i
++
)
wm8770
->
supplies
[
i
].
supply
=
wm8770_supply_names
[
i
];
ret
=
devm_regulator_bulk_get
(
&
spi
->
dev
,
ARRAY_SIZE
(
wm8770
->
supplies
),
wm8770
->
supplies
);
if
(
ret
)
{
dev_err
(
&
spi
->
dev
,
"Failed to request supplies: %d
\n
"
,
ret
);
return
ret
;
}
wm8770
->
disable_nb
[
0
].
notifier_call
=
wm8770_regulator_event_0
;
wm8770
->
disable_nb
[
1
].
notifier_call
=
wm8770_regulator_event_1
;
wm8770
->
disable_nb
[
2
].
notifier_call
=
wm8770_regulator_event_2
;
/* This should really be moved into the regulator core */
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
wm8770
->
supplies
);
i
++
)
{
ret
=
regulator_register_notifier
(
wm8770
->
supplies
[
i
].
consumer
,
&
wm8770
->
disable_nb
[
i
]);
if
(
ret
)
{
dev_err
(
&
spi
->
dev
,
"Failed to register regulator notifier: %d
\n
"
,
ret
);
}
}
wm8770
->
regmap
=
devm_regmap_init_spi
(
spi
,
&
wm8770_regmap
);
if
(
IS_ERR
(
wm8770
->
regmap
))
return
PTR_ERR
(
wm8770
->
regmap
);
spi_set_drvdata
(
spi
,
wm8770
);
ret
=
snd_soc_register_codec
(
&
spi
->
dev
,
...
...
@@ -710,7 +699,15 @@ static int __devinit wm8770_spi_probe(struct spi_device *spi)
static
int
__devexit
wm8770_spi_remove
(
struct
spi_device
*
spi
)
{
struct
wm8770_priv
*
wm8770
=
spi_get_drvdata
(
spi
);
int
i
;
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
wm8770
->
supplies
);
++
i
)
regulator_unregister_notifier
(
wm8770
->
supplies
[
i
].
consumer
,
&
wm8770
->
disable_nb
[
i
]);
snd_soc_unregister_codec
(
&
spi
->
dev
);
return
0
;
}
...
...
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