Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
raspberrypi-kernel
提交
38f7d75e
R
raspberrypi-kernel
项目概览
openeuler
/
raspberrypi-kernel
通知
13
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
raspberrypi-kernel
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
38f7d75e
编写于
8月 27, 2013
作者:
M
Mark Brown
浏览文件
操作
浏览文件
下载
差异文件
Merge remote-tracking branch 'asoc/topic/dapm' into asoc-core
上级
c22cff94
34742cb0
变更
11
隐藏空白更改
内联
并排
Showing
11 changed file
with
628 addition
and
493 deletion
+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
未找到文件。
include/sound/soc-dapm.h
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
浏览文件 @
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
;
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录