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
38f7d75e
Commit
38f7d75e
authored
Aug 27, 2013
by
Mark Brown
Browse files
Options
Browse Files
Download
Plain Diff
Merge remote-tracking branch 'asoc/topic/dapm' into asoc-core
parents
c22cff94
34742cb0
Changes
11
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
628 additions
and
493 deletions
+628
-493
include/sound/soc-dapm.h
include/sound/soc-dapm.h
+118
-81
include/sound/soc-dpcm.h
include/sound/soc-dpcm.h
+1
-1
include/sound/soc.h
include/sound/soc.h
+16
-13
sound/soc/codecs/tlv320aic3x.c
sound/soc/codecs/tlv320aic3x.c
+17
-35
sound/soc/codecs/twl6040.c
sound/soc/codecs/twl6040.c
+1
-3
sound/soc/codecs/wm8903.c
sound/soc/codecs/wm8903.c
+1
-3
sound/soc/codecs/wm8994.c
sound/soc/codecs/wm8994.c
+1
-3
sound/soc/codecs/wm8995.c
sound/soc/codecs/wm8995.c
+1
-4
sound/soc/codecs/wm_hubs.c
sound/soc/codecs/wm_hubs.c
+2
-6
sound/soc/soc-dapm.c
sound/soc/soc-dapm.c
+469
-335
sound/soc/soc-pcm.c
sound/soc/soc-pcm.c
+1
-9
No files found.
include/sound/soc-dapm.h
View file @
38f7d75e
...
...
@@ -70,121 +70,144 @@ struct device;
.num_kcontrols = 0, .reg = SND_SOC_NOPM, .event = wevent, \
.event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD}
#define SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert) \
.reg = wreg, .mask = 1, .shift = wshift, \
.on_val = winvert ? 0 : 1, .off_val = winvert ? 1 : 0
/* path domain */
#define SND_SOC_DAPM_PGA(wname, wreg, wshift, winvert,\
wcontrols, wncontrols) \
{ .id = snd_soc_dapm_pga, .name = wname, .reg = wreg, .shift = wshift, \
.invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = wncontrols}
{ .id = snd_soc_dapm_pga, .name = wname, \
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
.kcontrol_news = wcontrols, .num_kcontrols = wncontrols}
#define SND_SOC_DAPM_OUT_DRV(wname, wreg, wshift, winvert,\
wcontrols, wncontrols) \
{ .id = snd_soc_dapm_out_drv, .name = wname, .reg = wreg, .shift = wshift, \
.invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = wncontrols}
{ .id = snd_soc_dapm_out_drv, .name = wname, \
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
.kcontrol_news = wcontrols, .num_kcontrols = wncontrols}
#define SND_SOC_DAPM_MIXER(wname, wreg, wshift, winvert, \
wcontrols, wncontrols)\
{ .id = snd_soc_dapm_mixer, .name = wname, .reg = wreg, .shift = wshift, \
.invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = wncontrols}
{ .id = snd_soc_dapm_mixer, .name = wname, \
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
.kcontrol_news = wcontrols, .num_kcontrols = wncontrols}
#define SND_SOC_DAPM_MIXER_NAMED_CTL(wname, wreg, wshift, winvert, \
wcontrols, wncontrols)\
{ .id = snd_soc_dapm_mixer_named_ctl, .name = wname,
.reg = wreg,
\
.shift = wshift, .invert = winvert, .kcontrol_news = wcontrols
, \
.num_kcontrols = wncontrols}
{ .id = snd_soc_dapm_mixer_named_ctl, .name = wname, \
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert)
, \
.
kcontrol_news = wcontrols, .
num_kcontrols = wncontrols}
#define SND_SOC_DAPM_MICBIAS(wname, wreg, wshift, winvert) \
{ .id = snd_soc_dapm_micbias, .name = wname, .reg = wreg, .shift = wshift, \
.invert = winvert, .kcontrol_news = NULL, .num_kcontrols = 0}
{ .id = snd_soc_dapm_micbias, .name = wname, \
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
.kcontrol_news = NULL, .num_kcontrols = 0}
#define SND_SOC_DAPM_SWITCH(wname, wreg, wshift, winvert, wcontrols) \
{ .id = snd_soc_dapm_switch, .name = wname, .reg = wreg, .shift = wshift, \
.invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = 1}
{ .id = snd_soc_dapm_switch, .name = wname, \
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
.kcontrol_news = wcontrols, .num_kcontrols = 1}
#define SND_SOC_DAPM_MUX(wname, wreg, wshift, winvert, wcontrols) \
{ .id = snd_soc_dapm_mux, .name = wname, .reg = wreg,
.shift = wshift,
\
.
invert = winvert, .
kcontrol_news = wcontrols, .num_kcontrols = 1}
{ .id = snd_soc_dapm_mux, .name = wname, .reg = wreg, \
.kcontrol_news = wcontrols, .num_kcontrols = 1}
#define SND_SOC_DAPM_VIRT_MUX(wname, wreg, wshift, winvert, wcontrols) \
{ .id = snd_soc_dapm_virt_mux, .name = wname, .reg = wreg, .shift = wshift, \
.invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = 1}
{ .id = snd_soc_dapm_virt_mux, .name = wname, \
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
.kcontrol_news = wcontrols, .num_kcontrols = 1}
#define SND_SOC_DAPM_VALUE_MUX(wname, wreg, wshift, winvert, wcontrols) \
{ .id = snd_soc_dapm_value_mux, .name = wname,
.reg = wreg,
\
.shift = wshift, .invert = winvert, .kcontrol_news = wcontrols
, \
.num_kcontrols = 1}
{ .id = snd_soc_dapm_value_mux, .name = wname, \
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert)
, \
.
kcontrol_news = wcontrols, .
num_kcontrols = 1}
/* Simplified versions of above macros, assuming wncontrols = ARRAY_SIZE(wcontrols) */
#define SOC_PGA_ARRAY(wname, wreg, wshift, winvert,\
wcontrols) \
{ .id = snd_soc_dapm_pga, .name = wname, .reg = wreg, .shift = wshift, \
.invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols)}
{ .id = snd_soc_dapm_pga, .name = wname, \
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
.kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols)}
#define SOC_MIXER_ARRAY(wname, wreg, wshift, winvert, \
wcontrols)\
{ .id = snd_soc_dapm_mixer, .name = wname, .reg = wreg, .shift = wshift, \
.invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols)}
{ .id = snd_soc_dapm_mixer, .name = wname, \
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
.kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols)}
#define SOC_MIXER_NAMED_CTL_ARRAY(wname, wreg, wshift, winvert, \
wcontrols)\
{ .id = snd_soc_dapm_mixer_named_ctl, .name = wname,
.reg = wreg,
\
.shift = wshift, .invert = winvert, .kcontrol_news = wcontrols
, \
.num_kcontrols = ARRAY_SIZE(wcontrols)}
{ .id = snd_soc_dapm_mixer_named_ctl, .name = wname, \
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert)
, \
.
kcontrol_news = wcontrols, .
num_kcontrols = ARRAY_SIZE(wcontrols)}
/* path domain with event - event handler must return 0 for success */
#define SND_SOC_DAPM_PGA_E(wname, wreg, wshift, winvert, wcontrols, \
wncontrols, wevent, wflags) \
{ .id = snd_soc_dapm_pga, .name = wname, .reg = wreg, .shift = wshift, \
.invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = wncontrols, \
{ .id = snd_soc_dapm_pga, .name = wname, \
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
.kcontrol_news = wcontrols, .num_kcontrols = wncontrols, \
.event = wevent, .event_flags = wflags}
#define SND_SOC_DAPM_OUT_DRV_E(wname, wreg, wshift, winvert, wcontrols, \
wncontrols, wevent, wflags) \
{ .id = snd_soc_dapm_out_drv, .name = wname, .reg = wreg, .shift = wshift, \
.invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = wncontrols, \
{ .id = snd_soc_dapm_out_drv, .name = wname, \
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
.kcontrol_news = wcontrols, .num_kcontrols = wncontrols, \
.event = wevent, .event_flags = wflags}
#define SND_SOC_DAPM_MIXER_E(wname, wreg, wshift, winvert, wcontrols, \
wncontrols, wevent, wflags) \
{ .id = snd_soc_dapm_mixer, .name = wname, .reg = wreg, .shift = wshift, \
.invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = wncontrols, \
{ .id = snd_soc_dapm_mixer, .name = wname, \
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
.kcontrol_news = wcontrols, .num_kcontrols = wncontrols, \
.event = wevent, .event_flags = wflags}
#define SND_SOC_DAPM_MIXER_NAMED_CTL_E(wname, wreg, wshift, winvert, \
wcontrols, wncontrols, wevent, wflags) \
{ .id = snd_soc_dapm_mixer, .name = wname, .reg = wreg, .shift = wshift, \
.invert = winvert, .kcontrol_news = wcontrols, \
{ .id = snd_soc_dapm_mixer, .name = wname, \
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
.kcontrol_news = wcontrols, \
.num_kcontrols = wncontrols, .event = wevent, .event_flags = wflags}
#define SND_SOC_DAPM_SWITCH_E(wname, wreg, wshift, winvert, wcontrols, \
wevent, wflags) \
{ .id = snd_soc_dapm_switch, .name = wname, .reg = wreg, .shift = wshift, \
.invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = 1, \
{ .id = snd_soc_dapm_switch, .name = wname, \
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
.kcontrol_news = wcontrols, .num_kcontrols = 1, \
.event = wevent, .event_flags = wflags}
#define SND_SOC_DAPM_MUX_E(wname, wreg, wshift, winvert, wcontrols, \
wevent, wflags) \
{ .id = snd_soc_dapm_mux, .name = wname, .reg = wreg, .shift = wshift, \
.invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = 1, \
{ .id = snd_soc_dapm_mux, .name = wname, \
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
.kcontrol_news = wcontrols, .num_kcontrols = 1, \
.event = wevent, .event_flags = wflags}
#define SND_SOC_DAPM_VIRT_MUX_E(wname, wreg, wshift, winvert, wcontrols, \
wevent, wflags) \
{ .id = snd_soc_dapm_virt_mux, .name = wname, .reg = wreg, .shift = wshift, \
.invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = 1, \
{ .id = snd_soc_dapm_virt_mux, .name = wname, \
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
.kcontrol_news = wcontrols, .num_kcontrols = 1, \
.event = wevent, .event_flags = wflags}
/* additional sequencing control within an event type */
#define SND_SOC_DAPM_PGA_S(wname, wsubseq, wreg, wshift, winvert, \
wevent, wflags) \
{ .id = snd_soc_dapm_pga, .name = wname, .reg = wreg, .shift = wshift, \
.invert = winvert, .event = wevent, .event_flags = wflags, \
{ .id = snd_soc_dapm_pga, .name = wname, \
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
.event = wevent, .event_flags = wflags, \
.subseq = wsubseq}
#define SND_SOC_DAPM_SUPPLY_S(wname, wsubseq, wreg, wshift, winvert, wevent, \
wflags) \
{ .id = snd_soc_dapm_supply, .name = wname,
.reg = wreg,
\
.shift = wshift, .invert = winvert, .event = wevent
, \
.event_flags = wflags, .subseq = wsubseq}
{ .id = snd_soc_dapm_supply, .name = wname, \
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert)
, \
.event
= wevent, .event
_flags = wflags, .subseq = wsubseq}
/* Simplified versions of above macros, assuming wncontrols = ARRAY_SIZE(wcontrols) */
#define SOC_PGA_E_ARRAY(wname, wreg, wshift, winvert, wcontrols, \
wevent, wflags) \
{ .id = snd_soc_dapm_pga, .name = wname, .reg = wreg, .shift = wshift, \
.invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols), \
{ .id = snd_soc_dapm_pga, .name = wname, \
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
.kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols), \
.event = wevent, .event_flags = wflags}
#define SOC_MIXER_E_ARRAY(wname, wreg, wshift, winvert, wcontrols, \
wevent, wflags) \
{ .id = snd_soc_dapm_mixer, .name = wname, .reg = wreg, .shift = wshift, \
.invert = winvert, .kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols), \
{ .id = snd_soc_dapm_mixer, .name = wname, \
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
.kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols), \
.event = wevent, .event_flags = wflags}
#define SOC_MIXER_NAMED_CTL_E_ARRAY(wname, wreg, wshift, winvert, \
wcontrols, wevent, wflags) \
{ .id = snd_soc_dapm_mixer, .name = wname, .reg = wreg, .shift = wshift, \
.invert = winvert, .kcontrol_news = wcontrols, \
.num_kcontrols = ARRAY_SIZE(wcontrols), .event = wevent, .event_flags = wflags}
{ .id = snd_soc_dapm_mixer, .name = wname, \
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert), \
.kcontrol_news = wcontrols, .num_kcontrols = ARRAY_SIZE(wcontrols), \
.event = wevent, .event_flags = wflags}
/* events that are pre and post DAPM */
#define SND_SOC_DAPM_PRE(wname, wevent) \
...
...
@@ -199,35 +222,36 @@ struct device;
/* stream domain */
#define SND_SOC_DAPM_AIF_IN(wname, stname, wslot, wreg, wshift, winvert) \
{ .id = snd_soc_dapm_aif_in, .name = wname, .sname = stname, \
.reg = wreg, .shift = wshift, .invert = winvert
}
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert),
}
#define SND_SOC_DAPM_AIF_IN_E(wname, stname, wslot, wreg, wshift, winvert, \
wevent, wflags) \
{ .id = snd_soc_dapm_aif_in, .name = wname, .sname = stname, \
.reg = wreg, .shift = wshift, .invert = winvert
, \
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert)
, \
.event = wevent, .event_flags = wflags }
#define SND_SOC_DAPM_AIF_OUT(wname, stname, wslot, wreg, wshift, winvert) \
{ .id = snd_soc_dapm_aif_out, .name = wname, .sname = stname, \
.reg = wreg, .shift = wshift, .invert = winvert
}
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert),
}
#define SND_SOC_DAPM_AIF_OUT_E(wname, stname, wslot, wreg, wshift, winvert, \
wevent, wflags) \
{ .id = snd_soc_dapm_aif_out, .name = wname, .sname = stname, \
.reg = wreg, .shift = wshift, .invert = winvert
, \
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert)
, \
.event = wevent, .event_flags = wflags }
#define SND_SOC_DAPM_DAC(wname, stname, wreg, wshift, winvert) \
{ .id = snd_soc_dapm_dac, .name = wname, .sname = stname,
.reg = wreg,
\
.shift = wshift, .invert = winvert
}
{ .id = snd_soc_dapm_dac, .name = wname, .sname = stname, \
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert)
}
#define SND_SOC_DAPM_DAC_E(wname, stname, wreg, wshift, winvert, \
wevent, wflags) \
{ .id = snd_soc_dapm_dac, .name = wname, .sname = stname,
.reg = wreg,
\
.shift = wshift, .invert = winvert
, \
{ .id = snd_soc_dapm_dac, .name = wname, .sname = stname, \
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert)
, \
.event = wevent, .event_flags = wflags}
#define SND_SOC_DAPM_ADC(wname, stname, wreg, wshift, winvert) \
{ .id = snd_soc_dapm_adc, .name = wname, .sname = stname,
.reg = wreg,
\
.shift = wshift, .invert = winvert
}
{ .id = snd_soc_dapm_adc, .name = wname, .sname = stname, \
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert),
}
#define SND_SOC_DAPM_ADC_E(wname, stname, wreg, wshift, winvert, \
wevent, wflags) \
{ .id = snd_soc_dapm_adc, .name = wname, .sname = stname,
.reg = wreg,
\
.shift = wshift, .invert = winvert
, \
{ .id = snd_soc_dapm_adc, .name = wname, .sname = stname, \
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert)
, \
.event = wevent, .event_flags = wflags}
#define SND_SOC_DAPM_CLOCK_SUPPLY(wname) \
{ .id = snd_soc_dapm_clock_supply, .name = wname, \
...
...
@@ -241,14 +265,14 @@ struct device;
.on_val = won_val, .off_val = woff_val, .event = dapm_reg_event, \
.event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD}
#define SND_SOC_DAPM_SUPPLY(wname, wreg, wshift, winvert, wevent, wflags) \
{ .id = snd_soc_dapm_supply, .name = wname,
.reg = wreg,
\
.shift = wshift, .invert = winvert, .event = wevent
, \
.event_flags = wflags}
{ .id = snd_soc_dapm_supply, .name = wname, \
SND_SOC_DAPM_INIT_REG_VAL(wreg, wshift, winvert)
, \
.event
= wevent, .event
_flags = wflags}
#define SND_SOC_DAPM_REGULATOR_SUPPLY(wname, wdelay, wflags) \
{ .id = snd_soc_dapm_regulator_supply, .name = wname, \
.reg = SND_SOC_NOPM, .shift = wdelay, .event = dapm_regulator_event, \
.event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD, \
.
invert
= wflags}
.
on_val
= wflags}
/* dapm kcontrol types */
...
...
@@ -256,14 +280,26 @@ struct device;
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
.info = snd_soc_info_volsw, \
.get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \
.private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) }
.private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 0) }
#define SOC_DAPM_SINGLE_AUTODISABLE(xname, reg, shift, max, invert) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
.info = snd_soc_info_volsw, \
.get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \
.private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 1) }
#define SOC_DAPM_SINGLE_TLV(xname, reg, shift, max, invert, tlv_array) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
.info = snd_soc_info_volsw, \
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | SNDRV_CTL_ELEM_ACCESS_READWRITE,\
.tlv.p = (tlv_array), \
.get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \
.private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) }
.private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 0) }
#define SOC_DAPM_SINGLE_TLV_AUTODISABLE(xname, reg, shift, max, invert, tlv_array) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
.info = snd_soc_info_volsw, \
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | SNDRV_CTL_ELEM_ACCESS_READWRITE,\
.tlv.p = (tlv_array), \
.get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \
.private_value = SOC_SINGLE_VALUE(reg, shift, max, invert, 0) }
#define SOC_DAPM_ENUM(xname, xenum) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
.info = snd_soc_info_enum_double, \
...
...
@@ -333,6 +369,7 @@ struct snd_soc_dapm_route;
struct
snd_soc_dapm_context
;
struct
regulator
;
struct
snd_soc_dapm_widget_list
;
struct
snd_soc_dapm_update
;
int
dapm_reg_event
(
struct
snd_soc_dapm_widget
*
w
,
struct
snd_kcontrol
*
kcontrol
,
int
event
);
...
...
@@ -391,10 +428,12 @@ void snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream,
void
snd_soc_dapm_shutdown
(
struct
snd_soc_card
*
card
);
/* external DAPM widget events */
int
snd_soc_dapm_mixer_update_power
(
struct
snd_soc_dapm_widget
*
widget
,
struct
snd_kcontrol
*
kcontrol
,
int
connect
);
int
snd_soc_dapm_mux_update_power
(
struct
snd_soc_dapm_widget
*
widget
,
struct
snd_kcontrol
*
kcontrol
,
int
mux
,
struct
soc_enum
*
e
);
int
snd_soc_dapm_mixer_update_power
(
struct
snd_soc_dapm_context
*
dapm
,
struct
snd_kcontrol
*
kcontrol
,
int
connect
,
struct
snd_soc_dapm_update
*
update
);
int
snd_soc_dapm_mux_update_power
(
struct
snd_soc_dapm_context
*
dapm
,
struct
snd_kcontrol
*
kcontrol
,
int
mux
,
struct
soc_enum
*
e
,
struct
snd_soc_dapm_update
*
update
);
/* dapm sys fs - used by the core */
int
snd_soc_dapm_sys_add
(
struct
device
*
dev
);
...
...
@@ -424,6 +463,8 @@ void dapm_mark_io_dirty(struct snd_soc_dapm_context *dapm);
int
snd_soc_dapm_dai_get_connected_widgets
(
struct
snd_soc_dai
*
dai
,
int
stream
,
struct
snd_soc_dapm_widget_list
**
list
);
struct
snd_soc_codec
*
snd_soc_dapm_kcontrol_codec
(
struct
snd_kcontrol
*
kcontrol
);
/* dapm widget types */
enum
snd_soc_dapm_type
{
snd_soc_dapm_input
=
0
,
/* input pin */
...
...
@@ -455,6 +496,7 @@ enum snd_soc_dapm_type {
snd_soc_dapm_dai_in
,
/* link to DAI structure */
snd_soc_dapm_dai_out
,
snd_soc_dapm_dai_link
,
/* link between two DAI structures */
snd_soc_dapm_kcontrol
,
/* Auto-disabled kcontrol */
};
enum
snd_soc_dapm_subclass
{
...
...
@@ -485,7 +527,6 @@ struct snd_soc_dapm_path {
/* source (input) and sink (output) widgets */
struct
snd_soc_dapm_widget
*
source
;
struct
snd_soc_dapm_widget
*
sink
;
struct
snd_kcontrol
*
kcontrol
;
/* status */
u32
connect
:
1
;
/* source and sink widgets are connected */
...
...
@@ -498,6 +539,7 @@ struct snd_soc_dapm_path {
struct
list_head
list_source
;
struct
list_head
list_sink
;
struct
list_head
list_kcontrol
;
struct
list_head
list
;
};
...
...
@@ -518,12 +560,10 @@ struct snd_soc_dapm_widget {
/* dapm control */
int
reg
;
/* negative reg = no direct dapm */
unsigned
char
shift
;
/* bits to shift */
unsigned
int
value
;
/* widget current value */
unsigned
int
mask
;
/* non-shifted mask */
unsigned
int
on_val
;
/* on state value */
unsigned
int
off_val
;
/* off state value */
unsigned
char
power
:
1
;
/* block power status */
unsigned
char
invert
:
1
;
/* invert the power bit */
unsigned
char
active
:
1
;
/* active stream on DAC, ADC's */
unsigned
char
connected
:
1
;
/* connected codec pin */
unsigned
char
new
:
1
;
/* cnew complete */
...
...
@@ -559,7 +599,6 @@ struct snd_soc_dapm_widget {
};
struct
snd_soc_dapm_update
{
struct
snd_soc_dapm_widget
*
widget
;
struct
snd_kcontrol
*
kcontrol
;
int
reg
;
int
mask
;
...
...
@@ -573,8 +612,6 @@ struct snd_soc_dapm_context {
struct
delayed_work
delayed_work
;
unsigned
int
idle_bias_off
:
1
;
/* Use BIAS_OFF instead of STANDBY */
struct
snd_soc_dapm_update
*
update
;
void
(
*
seq_notifier
)(
struct
snd_soc_dapm_context
*
,
enum
snd_soc_dapm_type
,
int
);
...
...
include/sound/soc-dpcm.h
View file @
38f7d75e
...
...
@@ -133,6 +133,6 @@ void snd_soc_dpcm_be_set_state(struct snd_soc_pcm_runtime *be, int stream,
/* internal use only */
int
soc_dpcm_be_digital_mute
(
struct
snd_soc_pcm_runtime
*
fe
,
int
mute
);
int
soc_dpcm_debugfs_add
(
struct
snd_soc_pcm_runtime
*
rtd
);
int
soc_dpcm_runtime_update
(
struct
snd_soc_
dapm_widget
*
);
int
soc_dpcm_runtime_update
(
struct
snd_soc_
card
*
);
#endif
include/sound/soc.h
View file @
38f7d75e
...
...
@@ -30,13 +30,13 @@
/*
* Convenience kcontrol builders
*/
#define SOC_DOUBLE_VALUE(xreg, shift_left, shift_right, xmax, xinvert) \
#define SOC_DOUBLE_VALUE(xreg, shift_left, shift_right, xmax, xinvert
, xautodisable
) \
((unsigned long)&(struct soc_mixer_control) \
{.reg = xreg, .rreg = xreg, .shift = shift_left, \
.rshift = shift_right, .max = xmax, .platform_max = xmax, \
.invert = xinvert})
#define SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert) \
SOC_DOUBLE_VALUE(xreg, xshift, xshift, xmax, xinvert)
.invert = xinvert
, .autodisable = xautodisable
})
#define SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert
, xautodisable
) \
SOC_DOUBLE_VALUE(xreg, xshift, xshift, xmax, xinvert
, xautodisable
)
#define SOC_SINGLE_VALUE_EXT(xreg, xmax, xinvert) \
((unsigned long)&(struct soc_mixer_control) \
{.reg = xreg, .max = xmax, .platform_max = xmax, .invert = xinvert})
...
...
@@ -52,7 +52,7 @@
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
.info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\
.put = snd_soc_put_volsw, \
.private_value =
SOC_SINGLE_VALUE(reg, shift, max, invert
) }
.private_value =
SOC_SINGLE_VALUE(reg, shift, max, invert, 0
) }
#define SOC_SINGLE_RANGE(xname, xreg, xshift, xmin, xmax, xinvert) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
.info = snd_soc_info_volsw_range, .get = snd_soc_get_volsw_range, \
...
...
@@ -68,7 +68,7 @@
.tlv.p = (tlv_array), \
.info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\
.put = snd_soc_put_volsw, \
.private_value =
SOC_SINGLE_VALUE(reg, shift, max, invert
) }
.private_value =
SOC_SINGLE_VALUE(reg, shift, max, invert, 0
) }
#define SOC_SINGLE_SX_TLV(xname, xreg, xshift, xmin, xmax, tlv_array) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
...
...
@@ -97,7 +97,7 @@
.info = snd_soc_info_volsw, .get = snd_soc_get_volsw, \
.put = snd_soc_put_volsw, \
.private_value = SOC_DOUBLE_VALUE(reg, shift_left, shift_right, \
max, invert) }
max, invert
, 0
) }
#define SOC_DOUBLE_R(xname, reg_left, reg_right, xshift, xmax, xinvert) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
.info = snd_soc_info_volsw, \
...
...
@@ -119,7 +119,7 @@
.info = snd_soc_info_volsw, .get = snd_soc_get_volsw, \
.put = snd_soc_put_volsw, \
.private_value = SOC_DOUBLE_VALUE(reg, shift_left, shift_right, \
max, invert) }
max, invert
, 0
) }
#define SOC_DOUBLE_R_TLV(xname, reg_left, reg_right, xshift, xmax, xinvert, tlv_array) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
...
...
@@ -190,14 +190,14 @@
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
.info = snd_soc_info_volsw, \
.get = xhandler_get, .put = xhandler_put, \
.private_value = SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert) }
.private_value = SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert
, 0
) }
#define SOC_DOUBLE_EXT(xname, reg, shift_left, shift_right, max, invert,\
xhandler_get, xhandler_put) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
.info = snd_soc_info_volsw, \
.get = xhandler_get, .put = xhandler_put, \
.private_value = \
SOC_DOUBLE_VALUE(reg, shift_left, shift_right, max, invert) }
SOC_DOUBLE_VALUE(reg, shift_left, shift_right, max, invert
, 0
) }
#define SOC_SINGLE_EXT_TLV(xname, xreg, xshift, xmax, xinvert,\
xhandler_get, xhandler_put, tlv_array) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
...
...
@@ -206,7 +206,7 @@
.tlv.p = (tlv_array), \
.info = snd_soc_info_volsw, \
.get = xhandler_get, .put = xhandler_put, \
.private_value = SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert) }
.private_value = SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert
, 0
) }
#define SOC_DOUBLE_EXT_TLV(xname, xreg, shift_left, shift_right, xmax, xinvert,\
xhandler_get, xhandler_put, tlv_array) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
...
...
@@ -216,7 +216,7 @@
.info = snd_soc_info_volsw, \
.get = xhandler_get, .put = xhandler_put, \
.private_value = SOC_DOUBLE_VALUE(xreg, shift_left, shift_right, \
xmax, xinvert) }
xmax, xinvert
, 0
) }
#define SOC_DOUBLE_R_EXT_TLV(xname, reg_left, reg_right, xshift, xmax, xinvert,\
xhandler_get, xhandler_put, tlv_array) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
...
...
@@ -1038,6 +1038,7 @@ struct snd_soc_card {
/* Generic DAPM context for the card */
struct
snd_soc_dapm_context
dapm
;
struct
snd_soc_dapm_stats
dapm_stats
;
struct
snd_soc_dapm_update
*
update
;
#ifdef CONFIG_DEBUG_FS
struct
dentry
*
debugfs_card_root
;
...
...
@@ -1083,7 +1084,9 @@ struct snd_soc_pcm_runtime {
/* mixer control */
struct
soc_mixer_control
{
int
min
,
max
,
platform_max
;
unsigned
int
reg
,
rreg
,
shift
,
rshift
,
invert
;
unsigned
int
reg
,
rreg
,
shift
,
rshift
;
unsigned
int
invert
:
1
;
unsigned
int
autodisable
:
1
;
};
struct
soc_bytes
{
...
...
sound/soc/codecs/tlv320aic3x.c
View file @
38f7d75e
...
...
@@ -138,8 +138,7 @@ static const u8 aic3x_reg[AIC3X_CACHEREGNUM] = {
static
int
snd_soc_dapm_put_volsw_aic3x
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_value
*
ucontrol
)
{
struct
snd_soc_dapm_widget_list
*
wlist
=
snd_kcontrol_chip
(
kcontrol
);
struct
snd_soc_dapm_widget
*
widget
=
wlist
->
widgets
[
0
];
struct
snd_soc_codec
*
codec
=
snd_soc_dapm_kcontrol_codec
(
kcontrol
);
struct
soc_mixer_control
*
mc
=
(
struct
soc_mixer_control
*
)
kcontrol
->
private_value
;
unsigned
int
reg
=
mc
->
reg
;
...
...
@@ -147,10 +146,9 @@ static int snd_soc_dapm_put_volsw_aic3x(struct snd_kcontrol *kcontrol,
int
max
=
mc
->
max
;
unsigned
int
mask
=
(
1
<<
fls
(
max
))
-
1
;
unsigned
int
invert
=
mc
->
invert
;
unsigned
short
val
,
val_mask
;
int
ret
;
struct
snd_soc_dapm_path
*
path
;
int
found
=
0
;
unsigned
short
val
;
struct
snd_soc_dapm_update
update
;
int
connect
,
change
;
val
=
(
ucontrol
->
value
.
integer
.
value
[
0
]
&
mask
);
...
...
@@ -158,42 +156,26 @@ static int snd_soc_dapm_put_volsw_aic3x(struct snd_kcontrol *kcontrol,
if
(
val
)
val
=
mask
;
connect
=
!!
val
;
if
(
invert
)
val
=
mask
-
val
;
val_mask
=
mask
<<
shift
;
val
=
val
<<
shift
;
mutex_lock
(
&
widget
->
codec
->
mutex
);
if
(
snd_soc_test_bits
(
widget
->
codec
,
reg
,
val_mask
,
val
))
{
/* find dapm widget path assoc with kcontrol */
list_for_each_entry
(
path
,
&
widget
->
dapm
->
card
->
paths
,
list
)
{
if
(
path
->
kcontrol
!=
kcontrol
)
continue
;
mask
<<=
shift
;
val
<<=
shift
;
/* found, now check type */
found
=
1
;
if
(
val
)
/* new connection */
path
->
connect
=
invert
?
0
:
1
;
else
/* old connection must be powered down */
path
->
connect
=
invert
?
1
:
0
;
change
=
snd_soc_test_bits
(
codec
,
val
,
mask
,
reg
);
if
(
change
)
{
update
.
kcontrol
=
kcontrol
;
update
.
reg
=
reg
;
update
.
mask
=
mask
;
update
.
val
=
val
;
dapm_mark_dirty
(
path
->
source
,
"tlv320aic3x source"
);
dapm_mark_dirty
(
path
->
sink
,
"tlv320aic3x sink"
);
break
;
}
snd_soc_dapm_mixer_update_power
(
&
codec
->
dapm
,
kcontrol
,
connect
,
&
update
);
}
mutex_unlock
(
&
widget
->
codec
->
mutex
);
if
(
found
)
snd_soc_dapm_sync
(
widget
->
dapm
);
ret
=
snd_soc_update_bits_locked
(
widget
->
codec
,
reg
,
val_mask
,
val
);
return
ret
;
return
change
;
}
/*
...
...
sound/soc/codecs/twl6040.c
View file @
38f7d75e
...
...
@@ -437,9 +437,7 @@ static irqreturn_t twl6040_audio_handler(int irq, void *data)
static
int
twl6040_soc_dapm_put_vibra_enum
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_value
*
ucontrol
)
{
struct
snd_soc_dapm_widget_list
*
wlist
=
snd_kcontrol_chip
(
kcontrol
);
struct
snd_soc_dapm_widget
*
widget
=
wlist
->
widgets
[
0
];
struct
snd_soc_codec
*
codec
=
widget
->
codec
;
struct
snd_soc_codec
*
codec
=
snd_soc_dapm_kcontrol_codec
(
kcontrol
);
struct
soc_enum
*
e
=
(
struct
soc_enum
*
)
kcontrol
->
private_value
;
unsigned
int
val
;
...
...
sound/soc/codecs/wm8903.c
View file @
38f7d75e
...
...
@@ -364,9 +364,7 @@ static void wm8903_seq_notifier(struct snd_soc_dapm_context *dapm,
static
int
wm8903_class_w_put
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_value
*
ucontrol
)
{
struct
snd_soc_dapm_widget_list
*
wlist
=
snd_kcontrol_chip
(
kcontrol
);
struct
snd_soc_dapm_widget
*
widget
=
wlist
->
widgets
[
0
];
struct
snd_soc_codec
*
codec
=
widget
->
codec
;
struct
snd_soc_codec
*
codec
=
snd_soc_dapm_kcontrol_codec
(
kcontrol
);
struct
wm8903_priv
*
wm8903
=
snd_soc_codec_get_drvdata
(
codec
);
u16
reg
;
int
ret
;
...
...
sound/soc/codecs/wm8994.c
View file @
38f7d75e
...
...
@@ -1437,9 +1437,7 @@ SOC_DAPM_SINGLE("AIF1.1 Switch", WM8994_DAC2_RIGHT_MIXER_ROUTING,
static
int
wm8994_put_class_w
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_value
*
ucontrol
)
{
struct
snd_soc_dapm_widget_list
*
wlist
=
snd_kcontrol_chip
(
kcontrol
);
struct
snd_soc_dapm_widget
*
w
=
wlist
->
widgets
[
0
];
struct
snd_soc_codec
*
codec
=
w
->
codec
;
struct
snd_soc_codec
*
codec
=
snd_soc_dapm_kcontrol_codec
(
kcontrol
);
int
ret
;
ret
=
snd_soc_dapm_put_volsw
(
kcontrol
,
ucontrol
);
...
...
sound/soc/codecs/wm8995.c
View file @
38f7d75e
...
...
@@ -549,12 +549,9 @@ static int check_clk_sys(struct snd_soc_dapm_widget *source,
static
int
wm8995_put_class_w
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_value
*
ucontrol
)
{
struct
snd_soc_dapm_widget_list
*
wlist
=
snd_kcontrol_chip
(
kcontrol
);
struct
snd_soc_dapm_widget
*
w
=
wlist
->
widgets
[
0
];
struct
snd_soc_codec
*
codec
;
struct
snd_soc_codec
*
codec
=
snd_soc_dapm_kcontrol_codec
(
kcontrol
);
int
ret
;
codec
=
w
->
codec
;
ret
=
snd_soc_dapm_put_volsw
(
kcontrol
,
ucontrol
);
wm8995_update_class_w
(
codec
);
return
ret
;
...
...
sound/soc/codecs/wm_hubs.c
View file @
38f7d75e
...
...
@@ -699,9 +699,7 @@ EXPORT_SYMBOL_GPL(wm_hubs_update_class_w);
static
int
class_w_put_volsw
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_value
*
ucontrol
)
{
struct
snd_soc_dapm_widget_list
*
wlist
=
snd_kcontrol_chip
(
kcontrol
);
struct
snd_soc_dapm_widget
*
widget
=
wlist
->
widgets
[
0
];
struct
snd_soc_codec
*
codec
=
widget
->
codec
;
struct
snd_soc_codec
*
codec
=
snd_soc_dapm_kcontrol_codec
(
kcontrol
);
int
ret
;
ret
=
snd_soc_dapm_put_volsw
(
kcontrol
,
ucontrol
);
...
...
@@ -721,9 +719,7 @@ static int class_w_put_volsw(struct snd_kcontrol *kcontrol,
static
int
class_w_put_double
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_value
*
ucontrol
)
{
struct
snd_soc_dapm_widget_list
*
wlist
=
snd_kcontrol_chip
(
kcontrol
);
struct
snd_soc_dapm_widget
*
widget
=
wlist
->
widgets
[
0
];
struct
snd_soc_codec
*
codec
=
widget
->
codec
;
struct
snd_soc_codec
*
codec
=
snd_soc_dapm_kcontrol_codec
(
kcontrol
);
int
ret
;
ret
=
snd_soc_dapm_put_enum_double
(
kcontrol
,
ucontrol
);
...
...
sound/soc/soc-dapm.c
View file @
38f7d75e
...
...
@@ -47,6 +47,15 @@
#define DAPM_UPDATE_STAT(widget, val) widget->dapm->card->dapm_stats.val++;
static
int
snd_soc_dapm_add_path
(
struct
snd_soc_dapm_context
*
dapm
,
struct
snd_soc_dapm_widget
*
wsource
,
struct
snd_soc_dapm_widget
*
wsink
,
const
char
*
control
,
int
(
*
connected
)(
struct
snd_soc_dapm_widget
*
source
,
struct
snd_soc_dapm_widget
*
sink
));
static
struct
snd_soc_dapm_widget
*
snd_soc_dapm_new_control
(
struct
snd_soc_dapm_context
*
dapm
,
const
struct
snd_soc_dapm_widget
*
widget
);
/* dapm power sequences - make this per codec in the future */
static
int
dapm_up_seq
[]
=
{
[
snd_soc_dapm_pre
]
=
0
,
...
...
@@ -73,16 +82,18 @@ static int dapm_up_seq[] = {
[
snd_soc_dapm_hp
]
=
10
,
[
snd_soc_dapm_spk
]
=
10
,
[
snd_soc_dapm_line
]
=
10
,
[
snd_soc_dapm_post
]
=
11
,
[
snd_soc_dapm_kcontrol
]
=
11
,
[
snd_soc_dapm_post
]
=
12
,
};
static
int
dapm_down_seq
[]
=
{
[
snd_soc_dapm_pre
]
=
0
,
[
snd_soc_dapm_adc
]
=
1
,
[
snd_soc_dapm_hp
]
=
2
,
[
snd_soc_dapm_spk
]
=
2
,
[
snd_soc_dapm_line
]
=
2
,
[
snd_soc_dapm_out_drv
]
=
2
,
[
snd_soc_dapm_kcontrol
]
=
1
,
[
snd_soc_dapm_adc
]
=
2
,
[
snd_soc_dapm_hp
]
=
3
,
[
snd_soc_dapm_spk
]
=
3
,
[
snd_soc_dapm_line
]
=
3
,
[
snd_soc_dapm_out_drv
]
=
3
,
[
snd_soc_dapm_pga
]
=
4
,
[
snd_soc_dapm_switch
]
=
5
,
[
snd_soc_dapm_mixer_named_ctl
]
=
5
,
...
...
@@ -174,6 +185,176 @@ static inline struct snd_soc_dapm_widget *dapm_cnew_widget(
return
kmemdup
(
_widget
,
sizeof
(
*
_widget
),
GFP_KERNEL
);
}
struct
dapm_kcontrol_data
{
unsigned
int
value
;
struct
snd_soc_dapm_widget
*
widget
;
struct
list_head
paths
;
struct
snd_soc_dapm_widget_list
*
wlist
;
};
static
int
dapm_kcontrol_data_alloc
(
struct
snd_soc_dapm_widget
*
widget
,
struct
snd_kcontrol
*
kcontrol
)
{
struct
dapm_kcontrol_data
*
data
;
struct
soc_mixer_control
*
mc
;
data
=
kzalloc
(
sizeof
(
*
data
),
GFP_KERNEL
);
if
(
!
data
)
{
dev_err
(
widget
->
dapm
->
dev
,
"ASoC: can't allocate kcontrol data for %s
\n
"
,
widget
->
name
);
return
-
ENOMEM
;
}
INIT_LIST_HEAD
(
&
data
->
paths
);
switch
(
widget
->
id
)
{
case
snd_soc_dapm_switch
:
case
snd_soc_dapm_mixer
:
case
snd_soc_dapm_mixer_named_ctl
:
mc
=
(
struct
soc_mixer_control
*
)
kcontrol
->
private_value
;
if
(
mc
->
autodisable
)
{
struct
snd_soc_dapm_widget
template
;
memset
(
&
template
,
0
,
sizeof
(
template
));
template
.
reg
=
mc
->
reg
;
template
.
mask
=
(
1
<<
fls
(
mc
->
max
))
-
1
;
template
.
shift
=
mc
->
shift
;
if
(
mc
->
invert
)
template
.
off_val
=
mc
->
max
;
else
template
.
off_val
=
0
;
template
.
on_val
=
template
.
off_val
;
template
.
id
=
snd_soc_dapm_kcontrol
;
template
.
name
=
kcontrol
->
id
.
name
;
data
->
widget
=
snd_soc_dapm_new_control
(
widget
->
dapm
,
&
template
);
if
(
!
data
->
widget
)
{
kfree
(
data
);
return
-
ENOMEM
;
}
}
break
;
default:
break
;
}
kcontrol
->
private_data
=
data
;
return
0
;
}
static
void
dapm_kcontrol_free
(
struct
snd_kcontrol
*
kctl
)
{
struct
dapm_kcontrol_data
*
data
=
snd_kcontrol_chip
(
kctl
);
kfree
(
data
->
widget
);
kfree
(
data
->
wlist
);
kfree
(
data
);
}
static
struct
snd_soc_dapm_widget_list
*
dapm_kcontrol_get_wlist
(
const
struct
snd_kcontrol
*
kcontrol
)
{
struct
dapm_kcontrol_data
*
data
=
snd_kcontrol_chip
(
kcontrol
);
return
data
->
wlist
;
}
static
int
dapm_kcontrol_add_widget
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_soc_dapm_widget
*
widget
)
{
struct
dapm_kcontrol_data
*
data
=
snd_kcontrol_chip
(
kcontrol
);
struct
snd_soc_dapm_widget_list
*
new_wlist
;
unsigned
int
n
;
if
(
data
->
wlist
)
n
=
data
->
wlist
->
num_widgets
+
1
;
else
n
=
1
;
new_wlist
=
krealloc
(
data
->
wlist
,
sizeof
(
*
new_wlist
)
+
sizeof
(
widget
)
*
n
,
GFP_KERNEL
);
if
(
!
new_wlist
)
return
-
ENOMEM
;
new_wlist
->
widgets
[
n
-
1
]
=
widget
;
new_wlist
->
num_widgets
=
n
;
data
->
wlist
=
new_wlist
;
return
0
;
}
static
void
dapm_kcontrol_add_path
(
const
struct
snd_kcontrol
*
kcontrol
,
struct
snd_soc_dapm_path
*
path
)
{
struct
dapm_kcontrol_data
*
data
=
snd_kcontrol_chip
(
kcontrol
);
list_add_tail
(
&
path
->
list_kcontrol
,
&
data
->
paths
);
if
(
data
->
widget
)
{
snd_soc_dapm_add_path
(
data
->
widget
->
dapm
,
data
->
widget
,
path
->
source
,
NULL
,
NULL
);
}
}
static
bool
dapm_kcontrol_is_powered
(
const
struct
snd_kcontrol
*
kcontrol
)
{
struct
dapm_kcontrol_data
*
data
=
snd_kcontrol_chip
(
kcontrol
);
if
(
!
data
->
widget
)
return
true
;
return
data
->
widget
->
power
;
}
static
struct
list_head
*
dapm_kcontrol_get_path_list
(
const
struct
snd_kcontrol
*
kcontrol
)
{
struct
dapm_kcontrol_data
*
data
=
snd_kcontrol_chip
(
kcontrol
);
return
&
data
->
paths
;
}
#define dapm_kcontrol_for_each_path(path, kcontrol) \
list_for_each_entry(path, dapm_kcontrol_get_path_list(kcontrol), \
list_kcontrol)
static
unsigned
int
dapm_kcontrol_get_value
(
const
struct
snd_kcontrol
*
kcontrol
)
{
struct
dapm_kcontrol_data
*
data
=
snd_kcontrol_chip
(
kcontrol
);
return
data
->
value
;
}
static
bool
dapm_kcontrol_set_value
(
const
struct
snd_kcontrol
*
kcontrol
,
unsigned
int
value
)
{
struct
dapm_kcontrol_data
*
data
=
snd_kcontrol_chip
(
kcontrol
);
if
(
data
->
value
==
value
)
return
false
;
if
(
data
->
widget
)
data
->
widget
->
on_val
=
value
;
data
->
value
=
value
;
return
true
;
}
/**
* snd_soc_dapm_kcontrol_codec() - Returns the codec associated to a kcontrol
* @kcontrol: The kcontrol
*/
struct
snd_soc_codec
*
snd_soc_dapm_kcontrol_codec
(
struct
snd_kcontrol
*
kcontrol
)
{
return
dapm_kcontrol_get_wlist
(
kcontrol
)
->
widgets
[
0
]
->
codec
;
}
EXPORT_SYMBOL_GPL
(
snd_soc_dapm_kcontrol_codec
);
static
void
dapm_reset
(
struct
snd_soc_card
*
card
)
{
struct
snd_soc_dapm_widget
*
w
;
...
...
@@ -181,6 +362,7 @@ static void dapm_reset(struct snd_soc_card *card)
memset
(
&
card
->
dapm_stats
,
0
,
sizeof
(
card
->
dapm_stats
));
list_for_each_entry
(
w
,
&
card
->
widgets
,
list
)
{
w
->
new_power
=
w
->
power
;
w
->
power_checked
=
false
;
w
->
inputs
=
-
1
;
w
->
outputs
=
-
1
;
...
...
@@ -398,6 +580,7 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
case
snd_soc_dapm_spk
:
case
snd_soc_dapm_line
:
case
snd_soc_dapm_dai_link
:
case
snd_soc_dapm_kcontrol
:
p
->
connect
=
1
;
break
;
/* does affect routing - dynamically connected */
...
...
@@ -477,17 +660,12 @@ static int dapm_is_shared_kcontrol(struct snd_soc_dapm_context *dapm,
return
0
;
}
static
void
dapm_kcontrol_free
(
struct
snd_kcontrol
*
kctl
)
{
kfree
(
kctl
->
private_data
);
}
/*
* Determine if a kcontrol is shared. If it is, look it up. If it isn't,
* create it. Either way, add the widget into the control's widget list
*/
static
int
dapm_create_or_share_mixmux_kcontrol
(
struct
snd_soc_dapm_widget
*
w
,
int
kci
,
struct
snd_soc_dapm_path
*
path
)
int
kci
)
{
struct
snd_soc_dapm_context
*
dapm
=
w
->
dapm
;
struct
snd_card
*
card
=
dapm
->
card
->
snd_card
;
...
...
@@ -495,9 +673,6 @@ static int dapm_create_or_share_mixmux_kcontrol(struct snd_soc_dapm_widget *w,
size_t
prefix_len
;
int
shared
;
struct
snd_kcontrol
*
kcontrol
;
struct
snd_soc_dapm_widget_list
*
wlist
;
int
wlistentries
;
size_t
wlistsize
;
bool
wname_in_long_name
,
kcname_in_long_name
;
char
*
long_name
;
const
char
*
name
;
...
...
@@ -516,25 +691,6 @@ static int dapm_create_or_share_mixmux_kcontrol(struct snd_soc_dapm_widget *w,
shared
=
dapm_is_shared_kcontrol
(
dapm
,
w
,
&
w
->
kcontrol_news
[
kci
],
&
kcontrol
);
if
(
kcontrol
)
{
wlist
=
kcontrol
->
private_data
;
wlistentries
=
wlist
->
num_widgets
+
1
;
}
else
{
wlist
=
NULL
;
wlistentries
=
1
;
}
wlistsize
=
sizeof
(
struct
snd_soc_dapm_widget_list
)
+
wlistentries
*
sizeof
(
struct
snd_soc_dapm_widget
*
);
wlist
=
krealloc
(
wlist
,
wlistsize
,
GFP_KERNEL
);
if
(
wlist
==
NULL
)
{
dev_err
(
dapm
->
dev
,
"ASoC: can't allocate widget list for %s
\n
"
,
w
->
name
);
return
-
ENOMEM
;
}
wlist
->
num_widgets
=
wlistentries
;
wlist
->
widgets
[
wlistentries
-
1
]
=
w
;
if
(
!
kcontrol
)
{
if
(
shared
)
{
wname_in_long_name
=
false
;
...
...
@@ -557,7 +713,6 @@ static int dapm_create_or_share_mixmux_kcontrol(struct snd_soc_dapm_widget *w,
kcname_in_long_name
=
false
;
break
;
default:
kfree
(
wlist
);
return
-
EINVAL
;
}
}
...
...
@@ -572,10 +727,8 @@ static int dapm_create_or_share_mixmux_kcontrol(struct snd_soc_dapm_widget *w,
long_name
=
kasprintf
(
GFP_KERNEL
,
"%s %s"
,
w
->
name
+
prefix_len
,
w
->
kcontrol_news
[
kci
].
name
);
if
(
long_name
==
NULL
)
{
kfree
(
wlist
);
if
(
long_name
==
NULL
)
return
-
ENOMEM
;
}
name
=
long_name
;
}
else
if
(
wname_in_long_name
)
{
...
...
@@ -586,23 +739,33 @@ static int dapm_create_or_share_mixmux_kcontrol(struct snd_soc_dapm_widget *w,
name
=
w
->
kcontrol_news
[
kci
].
name
;
}
kcontrol
=
snd_soc_cnew
(
&
w
->
kcontrol_news
[
kci
],
wlist
,
name
,
kcontrol
=
snd_soc_cnew
(
&
w
->
kcontrol_news
[
kci
],
NULL
,
name
,
prefix
);
kcontrol
->
private_free
=
dapm_kcontrol_free
;
kfree
(
long_name
);
if
(
!
kcontrol
)
return
-
ENOMEM
;
kcontrol
->
private_free
=
dapm_kcontrol_free
;
ret
=
dapm_kcontrol_data_alloc
(
w
,
kcontrol
);
if
(
ret
)
{
snd_ctl_free_one
(
kcontrol
);
return
ret
;
}
ret
=
snd_ctl_add
(
card
,
kcontrol
);
if
(
ret
<
0
)
{
dev_err
(
dapm
->
dev
,
"ASoC: failed to add widget %s dapm kcontrol %s: %d
\n
"
,
w
->
name
,
name
,
ret
);
kfree
(
wlist
);
return
ret
;
}
}
kcontrol
->
private_data
=
wlist
;
ret
=
dapm_kcontrol_add_widget
(
kcontrol
,
w
);
if
(
ret
)
return
ret
;
w
->
kcontrols
[
kci
]
=
kcontrol
;
path
->
kcontrol
=
kcontrol
;
return
0
;
}
...
...
@@ -622,13 +785,15 @@ static int dapm_new_mixer(struct snd_soc_dapm_widget *w)
continue
;
if
(
w
->
kcontrols
[
i
])
{
path
->
kcontrol
=
w
->
kcontrols
[
i
]
;
dapm_kcontrol_add_path
(
w
->
kcontrols
[
i
],
path
)
;
continue
;
}
ret
=
dapm_create_or_share_mixmux_kcontrol
(
w
,
i
,
path
);
ret
=
dapm_create_or_share_mixmux_kcontrol
(
w
,
i
);
if
(
ret
<
0
)
return
ret
;
dapm_kcontrol_add_path
(
w
->
kcontrols
[
i
],
path
);
}
}
...
...
@@ -654,15 +819,12 @@ static int dapm_new_mux(struct snd_soc_dapm_widget *w)
return
-
EINVAL
;
}
path
=
list_first_entry
(
&
w
->
sources
,
struct
snd_soc_dapm_path
,
list_sink
);
ret
=
dapm_create_or_share_mixmux_kcontrol
(
w
,
0
,
path
);
ret
=
dapm_create_or_share_mixmux_kcontrol
(
w
,
0
);
if
(
ret
<
0
)
return
ret
;
list_for_each_entry
(
path
,
&
w
->
sources
,
list_sink
)
path
->
kcontrol
=
w
->
kcontrols
[
0
]
;
dapm_kcontrol_add_path
(
w
->
kcontrols
[
0
],
path
)
;
return
0
;
}
...
...
@@ -783,6 +945,7 @@ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget,
case
snd_soc_dapm_supply
:
case
snd_soc_dapm_regulator_supply
:
case
snd_soc_dapm_clock_supply
:
case
snd_soc_dapm_kcontrol
:
return
0
;
default:
break
;
...
...
@@ -878,6 +1041,7 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget,
case
snd_soc_dapm_supply
:
case
snd_soc_dapm_regulator_supply
:
case
snd_soc_dapm_clock_supply
:
case
snd_soc_dapm_kcontrol
:
return
0
;
default:
break
;
...
...
@@ -1032,7 +1196,7 @@ int dapm_regulator_event(struct snd_soc_dapm_widget *w,
int
ret
;
if
(
SND_SOC_DAPM_EVENT_ON
(
event
))
{
if
(
w
->
invert
&
SND_SOC_DAPM_REGULATOR_BYPASS
)
{
if
(
w
->
on_val
&
SND_SOC_DAPM_REGULATOR_BYPASS
)
{
ret
=
regulator_allow_bypass
(
w
->
regulator
,
false
);
if
(
ret
!=
0
)
dev_warn
(
w
->
dapm
->
dev
,
...
...
@@ -1042,7 +1206,7 @@ int dapm_regulator_event(struct snd_soc_dapm_widget *w,
return
regulator_enable
(
w
->
regulator
);
}
else
{
if
(
w
->
invert
&
SND_SOC_DAPM_REGULATOR_BYPASS
)
{
if
(
w
->
on_val
&
SND_SOC_DAPM_REGULATOR_BYPASS
)
{
ret
=
regulator_allow_bypass
(
w
->
regulator
,
true
);
if
(
ret
!=
0
)
dev_warn
(
w
->
dapm
->
dev
,
...
...
@@ -1214,10 +1378,9 @@ static void dapm_seq_insert(struct snd_soc_dapm_widget *new_widget,
list_add_tail
(
&
new_widget
->
power_list
,
list
);
}
static
void
dapm_seq_check_event
(
struct
snd_soc_
dapm_context
*
dapm
,
static
void
dapm_seq_check_event
(
struct
snd_soc_
card
*
card
,
struct
snd_soc_dapm_widget
*
w
,
int
event
)
{
struct
snd_soc_card
*
card
=
dapm
->
card
;
const
char
*
ev_name
;
int
power
,
ret
;
...
...
@@ -1251,55 +1414,50 @@ static void dapm_seq_check_event(struct snd_soc_dapm_context *dapm,
return
;
}
if
(
w
->
power
!=
power
)
if
(
w
->
new_
power
!=
power
)
return
;
if
(
w
->
event
&&
(
w
->
event_flags
&
event
))
{
pop_dbg
(
dapm
->
dev
,
card
->
pop_time
,
"pop test : %s %s
\n
"
,
pop_dbg
(
w
->
dapm
->
dev
,
card
->
pop_time
,
"pop test : %s %s
\n
"
,
w
->
name
,
ev_name
);
trace_snd_soc_dapm_widget_event_start
(
w
,
event
);
ret
=
w
->
event
(
w
,
NULL
,
event
);
trace_snd_soc_dapm_widget_event_done
(
w
,
event
);
if
(
ret
<
0
)
dev_err
(
dapm
->
dev
,
"ASoC: %s: %s event failed: %d
\n
"
,
dev_err
(
w
->
dapm
->
dev
,
"ASoC: %s: %s event failed: %d
\n
"
,
ev_name
,
w
->
name
,
ret
);
}
}
/* Apply the coalesced changes from a DAPM sequence */
static
void
dapm_seq_run_coalesced
(
struct
snd_soc_
dapm_context
*
dapm
,
static
void
dapm_seq_run_coalesced
(
struct
snd_soc_
card
*
card
,
struct
list_head
*
pending
)
{
struct
snd_soc_card
*
card
=
dapm
->
card
;
struct
snd_soc_dapm_widget
*
w
;
int
reg
,
power
;
int
reg
;
unsigned
int
value
=
0
;
unsigned
int
mask
=
0
;
unsigned
int
cur_mask
;
reg
=
list_first_entry
(
pending
,
struct
snd_soc_dapm_widget
,
power_list
)
->
reg
;
list_for_each_entry
(
w
,
pending
,
power_list
)
{
cur_mask
=
1
<<
w
->
shift
;
BUG_ON
(
reg
!=
w
->
reg
);
w
->
power
=
w
->
new_power
;
if
(
w
->
invert
)
power
=
!
w
->
power
;
mask
|=
w
->
mask
<<
w
->
shift
;
if
(
w
->
power
)
value
|=
w
->
on_val
<<
w
->
shift
;
else
power
=
w
->
power
;
mask
|=
cur_mask
;
if
(
power
)
value
|=
cur_mask
;
value
|=
w
->
off_val
<<
w
->
shift
;
pop_dbg
(
dapm
->
dev
,
card
->
pop_time
,
pop_dbg
(
w
->
dapm
->
dev
,
card
->
pop_time
,
"pop test : Queue %s: reg=0x%x, 0x%x/0x%x
\n
"
,
w
->
name
,
reg
,
value
,
mask
);
/* Check for events */
dapm_seq_check_event
(
dapm
,
w
,
SND_SOC_DAPM_PRE_PMU
);
dapm_seq_check_event
(
dapm
,
w
,
SND_SOC_DAPM_PRE_PMD
);
dapm_seq_check_event
(
card
,
w
,
SND_SOC_DAPM_PRE_PMU
);
dapm_seq_check_event
(
card
,
w
,
SND_SOC_DAPM_PRE_PMD
);
}
if
(
reg
>=
0
)
{
...
...
@@ -1309,7 +1467,7 @@ static void dapm_seq_run_coalesced(struct snd_soc_dapm_context *dapm,
w
=
list_first_entry
(
pending
,
struct
snd_soc_dapm_widget
,
power_list
);
pop_dbg
(
dapm
->
dev
,
card
->
pop_time
,
pop_dbg
(
w
->
dapm
->
dev
,
card
->
pop_time
,
"pop test : Applying 0x%x/0x%x to %x in %dms
\n
"
,
value
,
mask
,
reg
,
card
->
pop_time
);
pop_wait
(
card
->
pop_time
);
...
...
@@ -1317,8 +1475,8 @@ static void dapm_seq_run_coalesced(struct snd_soc_dapm_context *dapm,
}
list_for_each_entry
(
w
,
pending
,
power_list
)
{
dapm_seq_check_event
(
dapm
,
w
,
SND_SOC_DAPM_POST_PMU
);
dapm_seq_check_event
(
dapm
,
w
,
SND_SOC_DAPM_POST_PMD
);
dapm_seq_check_event
(
card
,
w
,
SND_SOC_DAPM_POST_PMU
);
dapm_seq_check_event
(
card
,
w
,
SND_SOC_DAPM_POST_PMD
);
}
}
...
...
@@ -1330,8 +1488,8 @@ static void dapm_seq_run_coalesced(struct snd_soc_dapm_context *dapm,
* Currently anything that requires more than a single write is not
* handled.
*/
static
void
dapm_seq_run
(
struct
snd_soc_
dapm_context
*
dapm
,
struct
list_head
*
list
,
int
event
,
bool
power_up
)
static
void
dapm_seq_run
(
struct
snd_soc_
card
*
card
,
struct
list_head
*
list
,
int
event
,
bool
power_up
)
{
struct
snd_soc_dapm_widget
*
w
,
*
n
;
LIST_HEAD
(
pending
);
...
...
@@ -1354,7 +1512,7 @@ static void dapm_seq_run(struct snd_soc_dapm_context *dapm,
if
(
sort
[
w
->
id
]
!=
cur_sort
||
w
->
reg
!=
cur_reg
||
w
->
dapm
!=
cur_dapm
||
w
->
subseq
!=
cur_subseq
)
{
if
(
!
list_empty
(
&
pending
))
dapm_seq_run_coalesced
(
c
ur_dapm
,
&
pending
);
dapm_seq_run_coalesced
(
c
ard
,
&
pending
);
if
(
cur_dapm
&&
cur_dapm
->
seq_notifier
)
{
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
dapm_up_seq
);
i
++
)
...
...
@@ -1414,7 +1572,7 @@ static void dapm_seq_run(struct snd_soc_dapm_context *dapm,
}
if
(
!
list_empty
(
&
pending
))
dapm_seq_run_coalesced
(
c
ur_dapm
,
&
pending
);
dapm_seq_run_coalesced
(
c
ard
,
&
pending
);
if
(
cur_dapm
&&
cur_dapm
->
seq_notifier
)
{
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
dapm_up_seq
);
i
++
)
...
...
@@ -1424,37 +1582,48 @@ static void dapm_seq_run(struct snd_soc_dapm_context *dapm,
}
}
static
void
dapm_widget_update
(
struct
snd_soc_
dapm_context
*
dapm
)
static
void
dapm_widget_update
(
struct
snd_soc_
card
*
card
)
{
struct
snd_soc_dapm_update
*
update
=
dapm
->
update
;
struct
snd_soc_dapm_widget
*
w
;
struct
snd_soc_dapm_update
*
update
=
card
->
update
;
struct
snd_soc_dapm_widget_list
*
wlist
;
struct
snd_soc_dapm_widget
*
w
=
NULL
;
unsigned
int
wi
;
int
ret
;
if
(
!
update
)
if
(
!
update
||
!
dapm_kcontrol_is_powered
(
update
->
kcontrol
)
)
return
;
w
=
update
->
widget
;
w
list
=
dapm_kcontrol_get_wlist
(
update
->
kcontrol
)
;
if
(
w
->
event
&&
(
w
->
event_flags
&
SND_SOC_DAPM_PRE_REG
))
{
ret
=
w
->
event
(
w
,
update
->
kcontrol
,
SND_SOC_DAPM_PRE_REG
);
if
(
ret
!=
0
)
dev_err
(
dapm
->
dev
,
"ASoC: %s DAPM pre-event failed: %d
\n
"
,
w
->
name
,
ret
);
for
(
wi
=
0
;
wi
<
wlist
->
num_widgets
;
wi
++
)
{
w
=
wlist
->
widgets
[
wi
];
if
(
w
->
event
&&
(
w
->
event_flags
&
SND_SOC_DAPM_PRE_REG
))
{
ret
=
w
->
event
(
w
,
update
->
kcontrol
,
SND_SOC_DAPM_PRE_REG
);
if
(
ret
!=
0
)
dev_err
(
w
->
dapm
->
dev
,
"ASoC: %s DAPM pre-event failed: %d
\n
"
,
w
->
name
,
ret
);
}
}
if
(
!
w
)
return
;
ret
=
soc_widget_update_bits_locked
(
w
,
update
->
reg
,
update
->
mask
,
update
->
val
);
if
(
ret
<
0
)
dev_err
(
dapm
->
dev
,
"ASoC: %s DAPM update failed: %d
\n
"
,
dev_err
(
w
->
dapm
->
dev
,
"ASoC: %s DAPM update failed: %d
\n
"
,
w
->
name
,
ret
);
if
(
w
->
event
&&
(
w
->
event_flags
&
SND_SOC_DAPM_POST_REG
))
{
ret
=
w
->
event
(
w
,
update
->
kcontrol
,
SND_SOC_DAPM_POST_REG
);
if
(
ret
!=
0
)
dev_err
(
dapm
->
dev
,
"ASoC: %s DAPM post-event failed: %d
\n
"
,
w
->
name
,
ret
);
for
(
wi
=
0
;
wi
<
wlist
->
num_widgets
;
wi
++
)
{
w
=
wlist
->
widgets
[
wi
];
if
(
w
->
event
&&
(
w
->
event_flags
&
SND_SOC_DAPM_POST_REG
))
{
ret
=
w
->
event
(
w
,
update
->
kcontrol
,
SND_SOC_DAPM_POST_REG
);
if
(
ret
!=
0
)
dev_err
(
w
->
dapm
->
dev
,
"ASoC: %s DAPM post-event failed: %d
\n
"
,
w
->
name
,
ret
);
}
}
}
...
...
@@ -1566,6 +1735,7 @@ static void dapm_widget_set_power(struct snd_soc_dapm_widget *w, bool power,
case
snd_soc_dapm_supply
:
case
snd_soc_dapm_regulator_supply
:
case
snd_soc_dapm_clock_supply
:
case
snd_soc_dapm_kcontrol
:
/* Supplies can't affect their outputs, only their inputs */
break
;
default:
...
...
@@ -1582,8 +1752,6 @@ static void dapm_widget_set_power(struct snd_soc_dapm_widget *w, bool power,
dapm_seq_insert
(
w
,
up_list
,
true
);
else
dapm_seq_insert
(
w
,
down_list
,
false
);
w
->
power
=
power
;
}
static
void
dapm_power_one_widget
(
struct
snd_soc_dapm_widget
*
w
,
...
...
@@ -1617,9 +1785,8 @@ static void dapm_power_one_widget(struct snd_soc_dapm_widget *w,
* o Input pin to Output pin (bypass, sidetone)
* o DAC to ADC (loopback).
*/
static
int
dapm_power_widgets
(
struct
snd_soc_
dapm_context
*
dapm
,
int
event
)
static
int
dapm_power_widgets
(
struct
snd_soc_
card
*
card
,
int
event
)
{
struct
snd_soc_card
*
card
=
dapm
->
card
;
struct
snd_soc_dapm_widget
*
w
;
struct
snd_soc_dapm_context
*
d
;
LIST_HEAD
(
up_list
);
...
...
@@ -1659,7 +1826,7 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
break
;
}
if
(
w
->
power
)
{
if
(
w
->
new_
power
)
{
d
=
w
->
dapm
;
/* Supplies and micbiases only bring the
...
...
@@ -1701,29 +1868,29 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
trace_snd_soc_dapm_walk_done
(
card
);
/* Run all the bias changes in parallel */
list_for_each_entry
(
d
,
&
dapm
->
card
->
dapm_list
,
list
)
list_for_each_entry
(
d
,
&
card
->
dapm_list
,
list
)
async_schedule_domain
(
dapm_pre_sequence_async
,
d
,
&
async_domain
);
async_synchronize_full_domain
(
&
async_domain
);
list_for_each_entry
(
w
,
&
down_list
,
power_list
)
{
dapm_seq_check_event
(
dapm
,
w
,
SND_SOC_DAPM_WILL_PMD
);
dapm_seq_check_event
(
card
,
w
,
SND_SOC_DAPM_WILL_PMD
);
}
list_for_each_entry
(
w
,
&
up_list
,
power_list
)
{
dapm_seq_check_event
(
dapm
,
w
,
SND_SOC_DAPM_WILL_PMU
);
dapm_seq_check_event
(
card
,
w
,
SND_SOC_DAPM_WILL_PMU
);
}
/* Power down widgets first; try to avoid amplifying pops. */
dapm_seq_run
(
dapm
,
&
down_list
,
event
,
false
);
dapm_seq_run
(
card
,
&
down_list
,
event
,
false
);
dapm_widget_update
(
dapm
);
dapm_widget_update
(
card
);
/* Now power up. */
dapm_seq_run
(
dapm
,
&
up_list
,
event
,
true
);
dapm_seq_run
(
card
,
&
up_list
,
event
,
true
);
/* Run all the bias changes in parallel */
list_for_each_entry
(
d
,
&
dapm
->
card
->
dapm_list
,
list
)
list_for_each_entry
(
d
,
&
card
->
dapm_list
,
list
)
async_schedule_domain
(
dapm_post_sequence_async
,
d
,
&
async_domain
);
async_synchronize_full_domain
(
&
async_domain
);
...
...
@@ -1734,7 +1901,7 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
d
->
stream_event
(
d
,
event
);
}
pop_dbg
(
dapm
->
dev
,
card
->
pop_time
,
pop_dbg
(
card
->
dev
,
card
->
pop_time
,
"DAPM sequencing finished, waiting %dms
\n
"
,
card
->
pop_time
);
pop_wait
(
card
->
pop_time
);
...
...
@@ -1769,8 +1936,8 @@ static ssize_t dapm_widget_power_read_file(struct file *file,
if
(
w
->
reg
>=
0
)
ret
+=
snprintf
(
buf
+
ret
,
PAGE_SIZE
-
ret
,
" - R%d(0x%x)
bit %d
"
,
w
->
reg
,
w
->
reg
,
w
->
shift
);
" - R%d(0x%x)
mask 0x%x
"
,
w
->
reg
,
w
->
reg
,
w
->
mask
<<
w
->
shift
);
ret
+=
snprintf
(
buf
+
ret
,
PAGE_SIZE
-
ret
,
"
\n
"
);
...
...
@@ -1907,22 +2074,14 @@ static inline void dapm_debugfs_cleanup(struct snd_soc_dapm_context *dapm)
#endif
/* test and update the power status of a mux widget */
static
int
soc_dapm_mux_update_power
(
struct
snd_soc_
dapm_widget
*
widget
,
static
int
soc_dapm_mux_update_power
(
struct
snd_soc_
card
*
card
,
struct
snd_kcontrol
*
kcontrol
,
int
mux
,
struct
soc_enum
*
e
)
{
struct
snd_soc_dapm_path
*
path
;
int
found
=
0
;
if
(
widget
->
id
!=
snd_soc_dapm_mux
&&
widget
->
id
!=
snd_soc_dapm_virt_mux
&&
widget
->
id
!=
snd_soc_dapm_value_mux
)
return
-
ENODEV
;
/* find dapm widget path assoc with kcontrol */
list_for_each_entry
(
path
,
&
widget
->
dapm
->
card
->
paths
,
list
)
{
if
(
path
->
kcontrol
!=
kcontrol
)
continue
;
dapm_kcontrol_for_each_path
(
path
,
kcontrol
)
{
if
(
!
path
->
name
||
!
e
->
texts
[
mux
])
continue
;
...
...
@@ -1937,73 +2096,68 @@ static int soc_dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
"mux disconnection"
);
path
->
connect
=
0
;
/* old connection must be powered down */
}
dapm_mark_dirty
(
path
->
sink
,
"mux change"
);
}
if
(
found
)
{
dapm_mark_dirty
(
widget
,
"mux change"
);
dapm_power_widgets
(
widget
->
dapm
,
SND_SOC_DAPM_STREAM_NOP
);
}
if
(
found
)
dapm_power_widgets
(
card
,
SND_SOC_DAPM_STREAM_NOP
);
return
found
;
}
int
snd_soc_dapm_mux_update_power
(
struct
snd_soc_dapm_widget
*
widget
,
struct
snd_kcontrol
*
kcontrol
,
int
mux
,
struct
soc_enum
*
e
)
int
snd_soc_dapm_mux_update_power
(
struct
snd_soc_dapm_context
*
dapm
,
struct
snd_kcontrol
*
kcontrol
,
int
mux
,
struct
soc_enum
*
e
,
struct
snd_soc_dapm_update
*
update
)
{
struct
snd_soc_card
*
card
=
widget
->
dapm
->
card
;
struct
snd_soc_card
*
card
=
dapm
->
card
;
int
ret
;
mutex_lock_nested
(
&
card
->
dapm_mutex
,
SND_SOC_DAPM_CLASS_RUNTIME
);
ret
=
soc_dapm_mux_update_power
(
widget
,
kcontrol
,
mux
,
e
);
card
->
update
=
update
;
ret
=
soc_dapm_mux_update_power
(
card
,
kcontrol
,
mux
,
e
);
card
->
update
=
NULL
;
mutex_unlock
(
&
card
->
dapm_mutex
);
if
(
ret
>
0
)
soc_dpcm_runtime_update
(
widget
);
soc_dpcm_runtime_update
(
card
);
return
ret
;
}
EXPORT_SYMBOL_GPL
(
snd_soc_dapm_mux_update_power
);
/* test and update the power status of a mixer or switch widget */
static
int
soc_dapm_mixer_update_power
(
struct
snd_soc_
dapm_widget
*
widget
,
static
int
soc_dapm_mixer_update_power
(
struct
snd_soc_
card
*
card
,
struct
snd_kcontrol
*
kcontrol
,
int
connect
)
{
struct
snd_soc_dapm_path
*
path
;
int
found
=
0
;
if
(
widget
->
id
!=
snd_soc_dapm_mixer
&&
widget
->
id
!=
snd_soc_dapm_mixer_named_ctl
&&
widget
->
id
!=
snd_soc_dapm_switch
)
return
-
ENODEV
;
/* find dapm widget path assoc with kcontrol */
list_for_each_entry
(
path
,
&
widget
->
dapm
->
card
->
paths
,
list
)
{
if
(
path
->
kcontrol
!=
kcontrol
)
continue
;
/* found, now check type */
dapm_kcontrol_for_each_path
(
path
,
kcontrol
)
{
found
=
1
;
path
->
connect
=
connect
;
dapm_mark_dirty
(
path
->
source
,
"mixer connection"
);
dapm_mark_dirty
(
path
->
sink
,
"mixer update"
);
}
if
(
found
)
{
dapm_mark_dirty
(
widget
,
"mixer update"
);
dapm_power_widgets
(
widget
->
dapm
,
SND_SOC_DAPM_STREAM_NOP
);
}
if
(
found
)
dapm_power_widgets
(
card
,
SND_SOC_DAPM_STREAM_NOP
);
return
found
;
}
int
snd_soc_dapm_mixer_update_power
(
struct
snd_soc_dapm_widget
*
widget
,
struct
snd_kcontrol
*
kcontrol
,
int
connect
)
int
snd_soc_dapm_mixer_update_power
(
struct
snd_soc_dapm_context
*
dapm
,
struct
snd_kcontrol
*
kcontrol
,
int
connect
,
struct
snd_soc_dapm_update
*
update
)
{
struct
snd_soc_card
*
card
=
widget
->
dapm
->
card
;
struct
snd_soc_card
*
card
=
dapm
->
card
;
int
ret
;
mutex_lock_nested
(
&
card
->
dapm_mutex
,
SND_SOC_DAPM_CLASS_RUNTIME
);
ret
=
soc_dapm_mixer_update_power
(
widget
,
kcontrol
,
connect
);
card
->
update
=
update
;
ret
=
soc_dapm_mixer_update_power
(
card
,
kcontrol
,
connect
);
card
->
update
=
NULL
;
mutex_unlock
(
&
card
->
dapm_mutex
);
if
(
ret
>
0
)
soc_dpcm_runtime_update
(
widget
);
soc_dpcm_runtime_update
(
card
);
return
ret
;
}
EXPORT_SYMBOL_GPL
(
snd_soc_dapm_mixer_update_power
);
...
...
@@ -2082,6 +2236,7 @@ static void dapm_free_path(struct snd_soc_dapm_path *path)
{
list_del
(
&
path
->
list_sink
);
list_del
(
&
path
->
list_source
);
list_del
(
&
path
->
list_kcontrol
);
list_del
(
&
path
->
list
);
kfree
(
path
);
}
...
...
@@ -2176,70 +2331,20 @@ int snd_soc_dapm_sync(struct snd_soc_dapm_context *dapm)
return
0
;
mutex_lock_nested
(
&
dapm
->
card
->
dapm_mutex
,
SND_SOC_DAPM_CLASS_RUNTIME
);
ret
=
dapm_power_widgets
(
dapm
,
SND_SOC_DAPM_STREAM_NOP
);
ret
=
dapm_power_widgets
(
dapm
->
card
,
SND_SOC_DAPM_STREAM_NOP
);
mutex_unlock
(
&
dapm
->
card
->
dapm_mutex
);
return
ret
;
}
EXPORT_SYMBOL_GPL
(
snd_soc_dapm_sync
);
static
int
snd_soc_dapm_add_route
(
struct
snd_soc_dapm_context
*
dapm
,
const
struct
snd_soc_dapm_route
*
route
)
static
int
snd_soc_dapm_add_path
(
struct
snd_soc_dapm_context
*
dapm
,
struct
snd_soc_dapm_widget
*
wsource
,
struct
snd_soc_dapm_widget
*
wsink
,
const
char
*
control
,
int
(
*
connected
)(
struct
snd_soc_dapm_widget
*
source
,
struct
snd_soc_dapm_widget
*
sink
))
{
struct
snd_soc_dapm_path
*
path
;
struct
snd_soc_dapm_widget
*
wsource
=
NULL
,
*
wsink
=
NULL
,
*
w
;
struct
snd_soc_dapm_widget
*
wtsource
=
NULL
,
*
wtsink
=
NULL
;
const
char
*
sink
;
const
char
*
control
=
route
->
control
;
const
char
*
source
;
char
prefixed_sink
[
80
];
char
prefixed_source
[
80
];
int
ret
=
0
;
if
(
dapm
->
codec
&&
dapm
->
codec
->
name_prefix
)
{
snprintf
(
prefixed_sink
,
sizeof
(
prefixed_sink
),
"%s %s"
,
dapm
->
codec
->
name_prefix
,
route
->
sink
);
sink
=
prefixed_sink
;
snprintf
(
prefixed_source
,
sizeof
(
prefixed_source
),
"%s %s"
,
dapm
->
codec
->
name_prefix
,
route
->
source
);
source
=
prefixed_source
;
}
else
{
sink
=
route
->
sink
;
source
=
route
->
source
;
}
/*
* find src and dest widgets over all widgets but favor a widget from
* current DAPM context
*/
list_for_each_entry
(
w
,
&
dapm
->
card
->
widgets
,
list
)
{
if
(
!
wsink
&&
!
(
strcmp
(
w
->
name
,
sink
)))
{
wtsink
=
w
;
if
(
w
->
dapm
==
dapm
)
wsink
=
w
;
continue
;
}
if
(
!
wsource
&&
!
(
strcmp
(
w
->
name
,
source
)))
{
wtsource
=
w
;
if
(
w
->
dapm
==
dapm
)
wsource
=
w
;
}
}
/* use widget from another DAPM context if not found from this */
if
(
!
wsink
)
wsink
=
wtsink
;
if
(
!
wsource
)
wsource
=
wtsource
;
if
(
wsource
==
NULL
)
{
dev_err
(
dapm
->
dev
,
"ASoC: no source widget found for %s
\n
"
,
route
->
source
);
return
-
ENODEV
;
}
if
(
wsink
==
NULL
)
{
dev_err
(
dapm
->
dev
,
"ASoC: no sink widget found for %s
\n
"
,
route
->
sink
);
return
-
ENODEV
;
}
int
ret
;
path
=
kzalloc
(
sizeof
(
struct
snd_soc_dapm_path
),
GFP_KERNEL
);
if
(
!
path
)
...
...
@@ -2247,8 +2352,9 @@ static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm,
path
->
source
=
wsource
;
path
->
sink
=
wsink
;
path
->
connected
=
route
->
connected
;
path
->
connected
=
connected
;
INIT_LIST_HEAD
(
&
path
->
list
);
INIT_LIST_HEAD
(
&
path
->
list_kcontrol
);
INIT_LIST_HEAD
(
&
path
->
list_source
);
INIT_LIST_HEAD
(
&
path
->
list_sink
);
...
...
@@ -2268,6 +2374,9 @@ static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm,
wsource
->
ext
=
1
;
}
dapm_mark_dirty
(
wsource
,
"Route added"
);
dapm_mark_dirty
(
wsink
,
"Route added"
);
/* connect static paths */
if
(
control
==
NULL
)
{
list_add
(
&
path
->
list
,
&
dapm
->
card
->
paths
);
...
...
@@ -2298,6 +2407,7 @@ static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm,
case
snd_soc_dapm_dai_in
:
case
snd_soc_dapm_dai_out
:
case
snd_soc_dapm_dai_link
:
case
snd_soc_dapm_kcontrol
:
list_add
(
&
path
->
list
,
&
dapm
->
card
->
paths
);
list_add
(
&
path
->
list_sink
,
&
wsink
->
sources
);
list_add
(
&
path
->
list_source
,
&
wsource
->
sinks
);
...
...
@@ -2329,15 +2439,78 @@ static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm,
return
0
;
}
dapm_mark_dirty
(
wsource
,
"Route added"
);
dapm_mark_dirty
(
wsink
,
"Route added"
);
return
0
;
err:
kfree
(
path
);
return
ret
;
}
static
int
snd_soc_dapm_add_route
(
struct
snd_soc_dapm_context
*
dapm
,
const
struct
snd_soc_dapm_route
*
route
)
{
struct
snd_soc_dapm_widget
*
wsource
=
NULL
,
*
wsink
=
NULL
,
*
w
;
struct
snd_soc_dapm_widget
*
wtsource
=
NULL
,
*
wtsink
=
NULL
;
const
char
*
sink
;
const
char
*
source
;
char
prefixed_sink
[
80
];
char
prefixed_source
[
80
];
int
ret
;
if
(
dapm
->
codec
&&
dapm
->
codec
->
name_prefix
)
{
snprintf
(
prefixed_sink
,
sizeof
(
prefixed_sink
),
"%s %s"
,
dapm
->
codec
->
name_prefix
,
route
->
sink
);
sink
=
prefixed_sink
;
snprintf
(
prefixed_source
,
sizeof
(
prefixed_source
),
"%s %s"
,
dapm
->
codec
->
name_prefix
,
route
->
source
);
source
=
prefixed_source
;
}
else
{
sink
=
route
->
sink
;
source
=
route
->
source
;
}
/*
* find src and dest widgets over all widgets but favor a widget from
* current DAPM context
*/
list_for_each_entry
(
w
,
&
dapm
->
card
->
widgets
,
list
)
{
if
(
!
wsink
&&
!
(
strcmp
(
w
->
name
,
sink
)))
{
wtsink
=
w
;
if
(
w
->
dapm
==
dapm
)
wsink
=
w
;
continue
;
}
if
(
!
wsource
&&
!
(
strcmp
(
w
->
name
,
source
)))
{
wtsource
=
w
;
if
(
w
->
dapm
==
dapm
)
wsource
=
w
;
}
}
/* use widget from another DAPM context if not found from this */
if
(
!
wsink
)
wsink
=
wtsink
;
if
(
!
wsource
)
wsource
=
wtsource
;
if
(
wsource
==
NULL
)
{
dev_err
(
dapm
->
dev
,
"ASoC: no source widget found for %s
\n
"
,
route
->
source
);
return
-
ENODEV
;
}
if
(
wsink
==
NULL
)
{
dev_err
(
dapm
->
dev
,
"ASoC: no sink widget found for %s
\n
"
,
route
->
sink
);
return
-
ENODEV
;
}
ret
=
snd_soc_dapm_add_path
(
dapm
,
wsource
,
wsink
,
route
->
control
,
route
->
connected
);
if
(
ret
)
goto
err
;
return
0
;
err:
dev_warn
(
dapm
->
dev
,
"ASoC: no dapm match for %s --> %s --> %s
\n
"
,
source
,
control
,
sink
);
kfree
(
path
);
source
,
route
->
control
,
sink
);
return
ret
;
}
...
...
@@ -2541,12 +2714,13 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_weak_routes);
*/
int
snd_soc_dapm_new_widgets
(
struct
snd_soc_dapm_context
*
dapm
)
{
struct
snd_soc_card
*
card
=
dapm
->
card
;
struct
snd_soc_dapm_widget
*
w
;
unsigned
int
val
;
mutex_lock_nested
(
&
dapm
->
card
->
dapm_mutex
,
SND_SOC_DAPM_CLASS_INIT
);
mutex_lock_nested
(
&
card
->
dapm_mutex
,
SND_SOC_DAPM_CLASS_INIT
);
list_for_each_entry
(
w
,
&
dapm
->
card
->
widgets
,
list
)
list_for_each_entry
(
w
,
&
card
->
widgets
,
list
)
{
if
(
w
->
new
)
continue
;
...
...
@@ -2556,7 +2730,7 @@ int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm)
sizeof
(
struct
snd_kcontrol
*
),
GFP_KERNEL
);
if
(
!
w
->
kcontrols
)
{
mutex_unlock
(
&
dapm
->
card
->
dapm_mutex
);
mutex_unlock
(
&
card
->
dapm_mutex
);
return
-
ENOMEM
;
}
}
...
...
@@ -2582,12 +2756,9 @@ int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm)
/* Read the initial power state from the device */
if
(
w
->
reg
>=
0
)
{
val
=
soc_widget_read
(
w
,
w
->
reg
);
val
&=
1
<<
w
->
shift
;
if
(
w
->
invert
)
val
=
!
val
;
if
(
val
)
val
=
soc_widget_read
(
w
,
w
->
reg
)
>>
w
->
shift
;
val
&=
w
->
mask
;
if
(
val
==
w
->
on_val
)
w
->
power
=
1
;
}
...
...
@@ -2597,8 +2768,8 @@ int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm)
dapm_debugfs_add_widget
(
w
);
}
dapm_power_widgets
(
dapm
,
SND_SOC_DAPM_STREAM_NOP
);
mutex_unlock
(
&
dapm
->
card
->
dapm_mutex
);
dapm_power_widgets
(
card
,
SND_SOC_DAPM_STREAM_NOP
);
mutex_unlock
(
&
card
->
dapm_mutex
);
return
0
;
}
EXPORT_SYMBOL_GPL
(
snd_soc_dapm_new_widgets
);
...
...
@@ -2615,8 +2786,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_new_widgets);
int
snd_soc_dapm_get_volsw
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_value
*
ucontrol
)
{
struct
snd_soc_
dapm_widget_list
*
wlist
=
snd_kcontrol_chip
(
kcontrol
);
struct
snd_soc_
dapm_widget
*
widget
=
wlist
->
widgets
[
0
]
;
struct
snd_soc_
codec
*
codec
=
snd_soc_dapm_kcontrol_codec
(
kcontrol
);
struct
snd_soc_
card
*
card
=
codec
->
card
;
struct
soc_mixer_control
*
mc
=
(
struct
soc_mixer_control
*
)
kcontrol
->
private_value
;
unsigned
int
reg
=
mc
->
reg
;
...
...
@@ -2624,17 +2795,24 @@ int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol,
int
max
=
mc
->
max
;
unsigned
int
mask
=
(
1
<<
fls
(
max
))
-
1
;
unsigned
int
invert
=
mc
->
invert
;
unsigned
int
val
;
if
(
snd_soc_volsw_is_stereo
(
mc
))
dev_warn
(
widget
->
dapm
->
dev
,
dev_warn
(
codec
->
dapm
.
dev
,
"ASoC: Control '%s' is stereo, which is not supported
\n
"
,
kcontrol
->
id
.
name
);
ucontrol
->
value
.
integer
.
value
[
0
]
=
(
snd_soc_read
(
widget
->
codec
,
reg
)
>>
shift
)
&
mask
;
mutex_lock_nested
(
&
card
->
dapm_mutex
,
SND_SOC_DAPM_CLASS_RUNTIME
);
if
(
dapm_kcontrol_is_powered
(
kcontrol
))
val
=
(
snd_soc_read
(
codec
,
reg
)
>>
shift
)
&
mask
;
else
val
=
dapm_kcontrol_get_value
(
kcontrol
);
mutex_unlock
(
&
card
->
dapm_mutex
);
if
(
invert
)
ucontrol
->
value
.
integer
.
value
[
0
]
=
max
-
ucontrol
->
value
.
integer
.
value
[
0
];
ucontrol
->
value
.
integer
.
value
[
0
]
=
max
-
val
;
else
ucontrol
->
value
.
integer
.
value
[
0
]
=
val
;
return
0
;
}
...
...
@@ -2652,9 +2830,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_get_volsw);
int
snd_soc_dapm_put_volsw
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_value
*
ucontrol
)
{
struct
snd_soc_dapm_widget_list
*
wlist
=
snd_kcontrol_chip
(
kcontrol
);
struct
snd_soc_dapm_widget
*
widget
=
wlist
->
widgets
[
0
];
struct
snd_soc_codec
*
codec
=
widget
->
codec
;
struct
snd_soc_codec
*
codec
=
snd_soc_dapm_kcontrol_codec
(
kcontrol
);
struct
snd_soc_card
*
card
=
codec
->
card
;
struct
soc_mixer_control
*
mc
=
(
struct
soc_mixer_control
*
)
kcontrol
->
private_value
;
...
...
@@ -2666,10 +2842,9 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
unsigned
int
val
;
int
connect
,
change
;
struct
snd_soc_dapm_update
update
;
int
wi
;
if
(
snd_soc_volsw_is_stereo
(
mc
))
dev_warn
(
widget
->
dapm
->
dev
,
dev_warn
(
codec
->
dapm
.
dev
,
"ASoC: Control '%s' is stereo, which is not supported
\n
"
,
kcontrol
->
id
.
name
);
...
...
@@ -2678,29 +2853,26 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
if
(
invert
)
val
=
max
-
val
;
mask
=
mask
<<
shift
;
val
=
val
<<
shift
;
mutex_lock_nested
(
&
card
->
dapm_mutex
,
SND_SOC_DAPM_CLASS_RUNTIME
);
change
=
snd_soc_test_bits
(
widget
->
codec
,
reg
,
mask
,
val
);
if
(
change
)
{
for
(
wi
=
0
;
wi
<
wlist
->
num_widgets
;
wi
++
)
{
widget
=
wlist
->
widgets
[
wi
];
dapm_kcontrol_set_value
(
kcontrol
,
val
);
widget
->
value
=
val
;
mask
=
mask
<<
shift
;
val
=
val
<<
shift
;
update
.
kcontrol
=
kcontrol
;
update
.
widget
=
widget
;
update
.
reg
=
reg
;
update
.
mask
=
mask
;
update
.
val
=
val
;
widget
->
dapm
->
update
=
&
update
;
change
=
snd_soc_test_bits
(
codec
,
reg
,
mask
,
val
)
;
if
(
change
)
{
update
.
kcontrol
=
kcontrol
;
update
.
reg
=
reg
;
update
.
mask
=
mask
;
update
.
val
=
val
;
soc_dapm_mixer_update_power
(
widget
,
kcontrol
,
connect
)
;
card
->
update
=
&
update
;
widget
->
dapm
->
update
=
NULL
;
}
soc_dapm_mixer_update_power
(
card
,
kcontrol
,
connect
);
card
->
update
=
NULL
;
}
mutex_unlock
(
&
card
->
dapm_mutex
);
...
...
@@ -2720,12 +2892,11 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_put_volsw);
int
snd_soc_dapm_get_enum_double
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_value
*
ucontrol
)
{
struct
snd_soc_dapm_widget_list
*
wlist
=
snd_kcontrol_chip
(
kcontrol
);
struct
snd_soc_dapm_widget
*
widget
=
wlist
->
widgets
[
0
];
struct
snd_soc_codec
*
codec
=
snd_soc_dapm_kcontrol_codec
(
kcontrol
);
struct
soc_enum
*
e
=
(
struct
soc_enum
*
)
kcontrol
->
private_value
;
unsigned
int
val
;
val
=
snd_soc_read
(
widget
->
codec
,
e
->
reg
);
val
=
snd_soc_read
(
codec
,
e
->
reg
);
ucontrol
->
value
.
enumerated
.
item
[
0
]
=
(
val
>>
e
->
shift_l
)
&
e
->
mask
;
if
(
e
->
shift_l
!=
e
->
shift_r
)
ucontrol
->
value
.
enumerated
.
item
[
1
]
=
...
...
@@ -2747,15 +2918,12 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_double);
int
snd_soc_dapm_put_enum_double
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_value
*
ucontrol
)
{
struct
snd_soc_dapm_widget_list
*
wlist
=
snd_kcontrol_chip
(
kcontrol
);
struct
snd_soc_dapm_widget
*
widget
=
wlist
->
widgets
[
0
];
struct
snd_soc_codec
*
codec
=
widget
->
codec
;
struct
snd_soc_codec
*
codec
=
snd_soc_dapm_kcontrol_codec
(
kcontrol
);
struct
snd_soc_card
*
card
=
codec
->
card
;
struct
soc_enum
*
e
=
(
struct
soc_enum
*
)
kcontrol
->
private_value
;
unsigned
int
val
,
mux
,
change
;
unsigned
int
mask
;
struct
snd_soc_dapm_update
update
;
int
wi
;
if
(
ucontrol
->
value
.
enumerated
.
item
[
0
]
>
e
->
max
-
1
)
return
-
EINVAL
;
...
...
@@ -2771,24 +2939,17 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
mutex_lock_nested
(
&
card
->
dapm_mutex
,
SND_SOC_DAPM_CLASS_RUNTIME
);
change
=
snd_soc_test_bits
(
widget
->
codec
,
e
->
reg
,
mask
,
val
);
change
=
snd_soc_test_bits
(
codec
,
e
->
reg
,
mask
,
val
);
if
(
change
)
{
for
(
wi
=
0
;
wi
<
wlist
->
num_widgets
;
wi
++
)
{
widget
=
wlist
->
widgets
[
wi
];
widget
->
value
=
val
;
update
.
kcontrol
=
kcontrol
;
update
.
reg
=
e
->
reg
;
update
.
mask
=
mask
;
update
.
val
=
val
;
card
->
update
=
&
update
;
update
.
kcontrol
=
kcontrol
;
update
.
widget
=
widget
;
update
.
reg
=
e
->
reg
;
update
.
mask
=
mask
;
update
.
val
=
val
;
widget
->
dapm
->
update
=
&
update
;
soc_dapm_mux_update_power
(
card
,
kcontrol
,
mux
,
e
);
soc_dapm_mux_update_power
(
widget
,
kcontrol
,
mux
,
e
);
widget
->
dapm
->
update
=
NULL
;
}
card
->
update
=
NULL
;
}
mutex_unlock
(
&
card
->
dapm_mutex
);
...
...
@@ -2806,11 +2967,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double);
int
snd_soc_dapm_get_enum_virt
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_value
*
ucontrol
)
{
struct
snd_soc_dapm_widget_list
*
wlist
=
snd_kcontrol_chip
(
kcontrol
);
struct
snd_soc_dapm_widget
*
widget
=
wlist
->
widgets
[
0
];
ucontrol
->
value
.
enumerated
.
item
[
0
]
=
widget
->
value
;
ucontrol
->
value
.
enumerated
.
item
[
0
]
=
dapm_kcontrol_get_value
(
kcontrol
);
return
0
;
}
EXPORT_SYMBOL_GPL
(
snd_soc_dapm_get_enum_virt
);
...
...
@@ -2825,30 +2982,22 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_virt);
int
snd_soc_dapm_put_enum_virt
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_value
*
ucontrol
)
{
struct
snd_soc_dapm_widget_list
*
wlist
=
snd_kcontrol_chip
(
kcontrol
);
struct
snd_soc_dapm_widget
*
widget
=
wlist
->
widgets
[
0
];
struct
snd_soc_codec
*
codec
=
widget
->
codec
;
struct
snd_soc_codec
*
codec
=
snd_soc_dapm_kcontrol_codec
(
kcontrol
);
struct
snd_soc_card
*
card
=
codec
->
card
;
unsigned
int
value
;
struct
soc_enum
*
e
=
(
struct
soc_enum
*
)
kcontrol
->
private_value
;
int
change
;
int
wi
;
if
(
ucontrol
->
value
.
enumerated
.
item
[
0
]
>=
e
->
max
)
return
-
EINVAL
;
mutex_lock_nested
(
&
card
->
dapm_mutex
,
SND_SOC_DAPM_CLASS_RUNTIME
);
change
=
widget
->
value
!=
ucontrol
->
value
.
enumerated
.
item
[
0
];
if
(
change
)
{
for
(
wi
=
0
;
wi
<
wlist
->
num_widgets
;
wi
++
)
{
widget
=
wlist
->
widgets
[
wi
];
widget
->
value
=
ucontrol
->
value
.
enumerated
.
item
[
0
];
soc_dapm_mux_update_power
(
widget
,
kcontrol
,
widget
->
value
,
e
);
}
}
value
=
ucontrol
->
value
.
enumerated
.
item
[
0
];
change
=
dapm_kcontrol_set_value
(
kcontrol
,
value
);
if
(
change
)
soc_dapm_mux_update_power
(
card
,
kcontrol
,
value
,
e
);
mutex_unlock
(
&
card
->
dapm_mutex
);
return
change
;
...
...
@@ -2871,12 +3020,11 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_virt);
int
snd_soc_dapm_get_value_enum_double
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_value
*
ucontrol
)
{
struct
snd_soc_dapm_widget_list
*
wlist
=
snd_kcontrol_chip
(
kcontrol
);
struct
snd_soc_dapm_widget
*
widget
=
wlist
->
widgets
[
0
];
struct
snd_soc_codec
*
codec
=
snd_soc_dapm_kcontrol_codec
(
kcontrol
);
struct
soc_enum
*
e
=
(
struct
soc_enum
*
)
kcontrol
->
private_value
;
unsigned
int
reg_val
,
val
,
mux
;
reg_val
=
snd_soc_read
(
widget
->
codec
,
e
->
reg
);
reg_val
=
snd_soc_read
(
codec
,
e
->
reg
);
val
=
(
reg_val
>>
e
->
shift_l
)
&
e
->
mask
;
for
(
mux
=
0
;
mux
<
e
->
max
;
mux
++
)
{
if
(
val
==
e
->
values
[
mux
])
...
...
@@ -2912,15 +3060,12 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_get_value_enum_double);
int
snd_soc_dapm_put_value_enum_double
(
struct
snd_kcontrol
*
kcontrol
,
struct
snd_ctl_elem_value
*
ucontrol
)
{
struct
snd_soc_dapm_widget_list
*
wlist
=
snd_kcontrol_chip
(
kcontrol
);
struct
snd_soc_dapm_widget
*
widget
=
wlist
->
widgets
[
0
];
struct
snd_soc_codec
*
codec
=
widget
->
codec
;
struct
snd_soc_codec
*
codec
=
snd_soc_dapm_kcontrol_codec
(
kcontrol
);
struct
snd_soc_card
*
card
=
codec
->
card
;
struct
soc_enum
*
e
=
(
struct
soc_enum
*
)
kcontrol
->
private_value
;
unsigned
int
val
,
mux
,
change
;
unsigned
int
mask
;
struct
snd_soc_dapm_update
update
;
int
wi
;
if
(
ucontrol
->
value
.
enumerated
.
item
[
0
]
>
e
->
max
-
1
)
return
-
EINVAL
;
...
...
@@ -2936,24 +3081,17 @@ int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol,
mutex_lock_nested
(
&
card
->
dapm_mutex
,
SND_SOC_DAPM_CLASS_RUNTIME
);
change
=
snd_soc_test_bits
(
widget
->
codec
,
e
->
reg
,
mask
,
val
);
change
=
snd_soc_test_bits
(
codec
,
e
->
reg
,
mask
,
val
);
if
(
change
)
{
for
(
wi
=
0
;
wi
<
wlist
->
num_widgets
;
wi
++
)
{
widget
=
wlist
->
widgets
[
wi
];
widget
->
value
=
val
;
update
.
kcontrol
=
kcontrol
;
update
.
reg
=
e
->
reg
;
update
.
mask
=
mask
;
update
.
val
=
val
;
card
->
update
=
&
update
;
update
.
kcontrol
=
kcontrol
;
update
.
widget
=
widget
;
update
.
reg
=
e
->
reg
;
update
.
mask
=
mask
;
update
.
val
=
val
;
widget
->
dapm
->
update
=
&
update
;
soc_dapm_mux_update_power
(
card
,
kcontrol
,
mux
,
e
);
soc_dapm_mux_update_power
(
widget
,
kcontrol
,
mux
,
e
);
widget
->
dapm
->
update
=
NULL
;
}
card
->
update
=
NULL
;
}
mutex_unlock
(
&
card
->
dapm_mutex
);
...
...
@@ -3050,7 +3188,7 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
return
NULL
;
}
if
(
w
->
invert
&
SND_SOC_DAPM_REGULATOR_BYPASS
)
{
if
(
w
->
on_val
&
SND_SOC_DAPM_REGULATOR_BYPASS
)
{
ret
=
regulator_allow_bypass
(
w
->
regulator
,
true
);
if
(
ret
!=
0
)
dev_warn
(
w
->
dapm
->
dev
,
...
...
@@ -3097,16 +3235,16 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
case
snd_soc_dapm_value_mux
:
w
->
power_check
=
dapm_generic_check_power
;
break
;
case
snd_soc_dapm_adc
:
case
snd_soc_dapm_aif_out
:
case
snd_soc_dapm_dai_out
:
w
->
power_check
=
dapm_adc_check_power
;
break
;
case
snd_soc_dapm_dac
:
case
snd_soc_dapm_aif_in
:
case
snd_soc_dapm_dai_in
:
w
->
power_check
=
dapm_dac_check_power
;
break
;
case
snd_soc_dapm_adc
:
case
snd_soc_dapm_aif_out
:
case
snd_soc_dapm_dac
:
case
snd_soc_dapm_aif_in
:
case
snd_soc_dapm_pga
:
case
snd_soc_dapm_out_drv
:
case
snd_soc_dapm_input
:
...
...
@@ -3122,6 +3260,7 @@ snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
case
snd_soc_dapm_supply
:
case
snd_soc_dapm_regulator_supply
:
case
snd_soc_dapm_clock_supply
:
case
snd_soc_dapm_kcontrol
:
w
->
power_check
=
dapm_supply_check_power
;
break
;
default:
...
...
@@ -3386,9 +3525,6 @@ int snd_soc_dapm_link_dai_widgets(struct snd_soc_card *card)
{
struct
snd_soc_dapm_widget
*
dai_w
,
*
w
;
struct
snd_soc_dai
*
dai
;
struct
snd_soc_dapm_route
r
;
memset
(
&
r
,
0
,
sizeof
(
r
));
/* For each DAI widget... */
list_for_each_entry
(
dai_w
,
&
card
->
widgets
,
list
)
{
...
...
@@ -3415,29 +3551,27 @@ int snd_soc_dapm_link_dai_widgets(struct snd_soc_card *card)
break
;
}
if
(
!
w
->
sname
)
if
(
!
w
->
sname
||
!
strstr
(
w
->
sname
,
dai_w
->
name
)
)
continue
;
if
(
dai
->
driver
->
playback
.
stream_name
&&
strstr
(
w
->
sname
,
dai
->
driver
->
playback
.
stream_name
))
{
r
.
source
=
dai
->
playback_widget
->
name
;
r
.
sink
=
w
->
name
;
dev_dbg
(
dai
->
dev
,
"%s -> %s
\n
"
,
r
.
source
,
r
.
sink
);
dai
->
playback_widget
->
name
,
w
->
name
);
snd_soc_dapm_add_route
(
w
->
dapm
,
&
r
);
snd_soc_dapm_add_path
(
w
->
dapm
,
dai
->
playback_widget
,
w
,
NULL
,
NULL
);
}
if
(
dai
->
driver
->
capture
.
stream_name
&&
strstr
(
w
->
sname
,
dai
->
driver
->
capture
.
stream_name
))
{
r
.
source
=
w
->
name
;
r
.
sink
=
dai
->
capture_widget
->
name
;
dev_dbg
(
dai
->
dev
,
"%s -> %s
\n
"
,
r
.
source
,
r
.
sink
);
w
->
name
,
dai
->
capture_widget
->
name
);
snd_soc_dapm_add_route
(
w
->
dapm
,
&
r
);
snd_soc_dapm_add_path
(
w
->
dapm
,
w
,
dai
->
capture_widget
,
NULL
,
NULL
);
}
}
}
...
...
@@ -3499,7 +3633,7 @@ static void soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream,
}
}
dapm_power_widgets
(
&
rtd
->
card
->
dapm
,
event
);
dapm_power_widgets
(
rtd
->
card
,
event
);
}
/**
...
...
@@ -3768,7 +3902,7 @@ static void soc_dapm_shutdown_codec(struct snd_soc_dapm_context *dapm)
if
(
dapm
->
bias_level
==
SND_SOC_BIAS_ON
)
snd_soc_dapm_set_bias_level
(
dapm
,
SND_SOC_BIAS_PREPARE
);
dapm_seq_run
(
dapm
,
&
down_list
,
0
,
false
);
dapm_seq_run
(
card
,
&
down_list
,
0
,
false
);
if
(
dapm
->
bias_level
==
SND_SOC_BIAS_PREPARE
)
snd_soc_dapm_set_bias_level
(
dapm
,
SND_SOC_BIAS_STANDBY
);
...
...
sound/soc/soc-pcm.c
View file @
38f7d75e
...
...
@@ -1833,18 +1833,10 @@ static int dpcm_run_old_update(struct snd_soc_pcm_runtime *fe, int stream)
/* Called by DAPM mixer/mux changes to update audio routing between PCMs and
* any DAI links.
*/
int
soc_dpcm_runtime_update
(
struct
snd_soc_
dapm_widget
*
widget
)
int
soc_dpcm_runtime_update
(
struct
snd_soc_
card
*
card
)
{
struct
snd_soc_card
*
card
;
int
i
,
old
,
new
,
paths
;
if
(
widget
->
codec
)
card
=
widget
->
codec
->
card
;
else
if
(
widget
->
platform
)
card
=
widget
->
platform
->
card
;
else
return
-
EINVAL
;
mutex_lock_nested
(
&
card
->
mutex
,
SND_SOC_CARD_CLASS_RUNTIME
);
for
(
i
=
0
;
i
<
card
->
num_rtd
;
i
++
)
{
struct
snd_soc_dapm_widget_list
*
list
;
...
...
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