高通滤波器怎么设置耳机的解决方案都有哪些

客户端下载
发送验证码
未注册的用户手机验证后自动登录
30天内免登录
社交账号登录
绑定手机号
发送验证码
举报举报原因:广告营销地域攻击色情低俗人身攻击诈骗骚扰谣言反动其他取消 提交
&&&&&正文高通的这项合作,让耳机更智能,不是阿里也不是腾讯 00:32
服务员小蓝
时隔一年,百度AI开发者大会盛大召开。会上,高通市场副总裁侯明娟受邀出席,并发表演讲。基于高通和百度的合作,已经在高通全新的低功耗蓝牙系统级芯片 QCC5100 系列,以及高通智能音频平台开发套件上实现对百度 DuerOS 的支持。DuerOS是百度度秘事业部研发的对话式人工智能系统,搭载了此系统的设备,可让用户以自然语言对话的交互方式,实现影音娱乐、信息查询、生活服务、出行路况等10大类目的200多项功能的操作。QCC5100 系列是高通推出的全新低功耗蓝牙系统级芯片,旨在帮助制造商开发新一代功能丰富的耳机,以及满足消费者对无线音频设备中卓越音质、更长电池续航和播放时长的需要。这项合作将DuerOS引入到基于高通解决方案的蓝牙耳机和音响设备中,即可以以极低的功耗唤醒语音助手,还可以享受更顶级的音质。
来源:红观未来
来源:北京时间
来源:星商会
来源:零镜网
来源:zol中关村在线
来源:数码集市
来源:玩转科技
来源:cnBeta
来源:华强微电子
来源:DIGITIMES
来源:品途商业评论
来源:小明看世界
来源:亿欧
来源:极度网
来源:灰鸽胡侃
来源:通缉伯乐886
来源:看看网上那些事儿
来源:皮克干cr
来源:芯智讯
来源:TechWeb.com.cn
来源:强力科技达人
来源:电脑之家
来源:身边的神奇科技
来源:爱活网
来源:数字经济旁观者DISCOVER·POTENTIAL
高通平台的耳机检测(msm8909)
记录高通msm8909耳机检测的机制,相关代码
kernel/arch/arm/boot/dts/qcom/msm8909-qrd-skuc.dtsi
compatible = "qcom,msm8x16-audio-codec";
qcom,model = "msm8909-skuc-snd-card";
qcom,msm-snd-card-id = &0&;
qcom,msm-codec-type = "internal";
qcom,msm-ext-pa = "primary";
qcom,msm-mclk-freq = &9600000&;
qcom,msm-mbhc-hphl-swh = &0&;
qcom,msm-mbhc-gnd-swh = &0&;
qcom,msm-hs-micbias-type = "internal";
qcom,msm-micbias1-ext-
qcom,msm-micbias2-ext-
qcom,audio-routing =
"RX_BIAS", "MCLK",
"SPK_RX_BIAS", "MCLK",
"INT_LDO_H", "MCLK",
"MIC BIAS Internal1", "Handset Mic",
"MIC BIAS Internal2", "Headset Mic",
"MIC BIAS Internal3", "Secondary Mic",
"AMIC1", "MIC BIAS Internal1",
"AMIC2", "MIC BIAS Internal2",
"AMIC3", "MIC BIAS Internal3";
pinctrl-names = "cdc_lines_act",
"cdc_lines_sus";
pinctrl-0 = &&cdc_pdm_lines_act&;
pinctrl-1 = &&cdc_pdm_lines_sus&;
asoc-platform = &&pcm0&, &&pcm1&, &&voip&, &&voice&,
&&loopback&, &&compress&, &&hostless&,
&&afe&, &&lsm&, &&routing&, &&lpa&,
&&voice_svc&;
asoc-platform-names = "msm-pcm-dsp.0", "msm-pcm-dsp.1",
"msm-voip-dsp", "msm-pcm-voice", "msm-pcm-loopback",
"msm-compress-dsp", "msm-pcm-hostless", "msm-pcm-afe",
"msm-lsm-client", "msm-pcm-routing", "msm-pcm-lpa",
"msm-voice-svc";
asoc-cpu = &&dai_pri_auxpcm&, &&dai_hdmi&,
&&dai_mi2s0&, &&dai_mi2s1&, &&dai_mi2s2&, &&dai_mi2s3&,
&&sb_0_rx&, &&sb_0_tx&, &&sb_1_rx&, &&sb_1_tx&,
&&sb_3_rx&, &&sb_3_tx&, &&sb_4_rx&, &&sb_4_tx&,
&&bt_sco_rx&, &&bt_sco_tx&, &&int_fm_rx&, &&int_fm_tx&,
&&afe_pcm_rx&, &&afe_pcm_tx&, &&afe_proxy_rx&, &&afe_proxy_tx&,
&&incall_record_rx&, &&incall_record_tx&, &&incall_music_rx&,
&&incall_music_2_rx&;
asoc-cpu-names = "msm-dai-q6-auxpcm.1", "msm-dai-q6-hdmi.8",
"msm-dai-q6-mi2s.0", "msm-dai-q6-mi2s.1",
"msm-dai-q6-mi2s.2", "msm-dai-q6-mi2s.3",
"msm-dai-q6-dev.16384", "msm-dai-q6-dev.16385",
"msm-dai-q6-dev.16386", "msm-dai-q6-dev.16387",
"msm-dai-q6-dev.16390", "msm-dai-q6-dev.16391",
"msm-dai-q6-dev.16392", "msm-dai-q6-dev.16393",
"msm-dai-q6-dev.12288", "msm-dai-q6-dev.12289",
"msm-dai-q6-dev.12292", "msm-dai-q6-dev.12293",
"msm-dai-q6-dev.224", "msm-dai-q6-dev.225",
"msm-dai-q6-dev.241", "msm-dai-q6-dev.240",
"msm-dai-q6-dev.32771", "msm-dai-q6-dev.32772",
"msm-dai-q6-dev.32773", "msm-dai-q6-dev.32770";
asoc-codec = &&stub_codec&, &&pm8909_conga_dig&;
asoc-codec-names = "msm-stub-codec.1", "tombak_codec";
kernel/arch/arm/boot/dts/qcom/msm-pm8909.dtsi
pm8909_conga_dig: 8909_wcd_codec@f000 {
compatible = "qcom,msm8x16_wcd_codec";
reg = &0xf000 0x100&;
interrupt-parent = &&spmi_bus&;
interrupts = &0x1 0xf0 0x0&,
&0x1 0xf0 0x1&,
&0x1 0xf0 0x2&,
&0x1 0xf0 0x3&,
&0x1 0xf0 0x4&,
&0x1 0xf0 0x5&,
&0x1 0xf0 0x6&,
&0x1 0xf0 0x7&;
interrupt-names = "spk_cnp_int",
"spk_clip_int",
"spk_ocp_int",
"ins_rem_det1",
"but_rel_det",
"but_press_det",
"ins_rem_det",
"mbhc_int";
cdc-vdda-cp-supply = &&pm8909_s2&;
qcom,cdc-vdda-cp-voltage = &0000&;
qcom,cdc-vdda-cp-current = &500000&;
cdc-vdda-h-supply = &&pm8909_l5&;
qcom,cdc-vdda-h-voltage = &0000&;
qcom,cdc-vdda-h-current = &10000&;
cdc-vdd-px-supply = &&pm8909_l5&;
qcom,cdc-vdd-px-voltage = &0000&;
qcom,cdc-vdd-px-current = &5000&;
cdc-vdd-pa-supply = &&pm8909_s2&;
qcom,cdc-vdd-pa-voltage = &0000&;
qcom,cdc-vdd-pa-current = &260000&;
cdc-vdd-mic-bias-supply = &&pm8909_l13&;
qcom,cdc-vdd-mic-bias-voltage = &5000&;
qcom,cdc-vdd-mic-bias-current = &5000&;
qcom,cdc-mclk-clk-rate = &9600000&;
qcom,cdc-static-supplies = "cdc-vdda-h",
"cdc-vdd-px",
"cdc-vdd-pa",
"cdc-vdda-cp";
qcom,cdc-on-demand-supplies = "cdc-vdd-mic-bias";
pm8909_conga_analog: 8909_wcd_codec@f100 {
compatible = "qcom,msm8x16_wcd_codec";
reg = &0xf100 0x100&;
interrupt-parent = &&spmi_bus&;
interrupts = &0x1 0xf1 0x0&,
&0x1 0xf1 0x1&,
&0x1 0xf1 0x2&,
&0x1 0xf1 0x3&,
&0x1 0xf1 0x4&,
&0x1 0xf1 0x5&;
interrupt-names = "ear_ocp_int",
"hphr_ocp_int",
"hphl_ocp_det",
"ear_cnp_int",
"hphr_cnp_int",
"hphl_cnp_int";
msm8909的耳机接口在pm8909上,耳机检测脚是HS_DET。
qcom,msm-mbhc-hphl-swh = &0&;
这里设置不同的耳机插口类型(0或者1),简单的理解就是低电平检测还是高电平检测(可参考)
kernel/sound/soc/codecs/msm8x16-wcd.c
static const struct wcd_mbhc_intr intr_ids = {
.mbhc_sw_intr =
MSM8X16_WCD_IRQ_MBHC_HS_DET,
.mbhc_btn_press_intr = MSM8X16_WCD_IRQ_MBHC_PRESS,
.mbhc_btn_release_intr = MSM8X16_WCD_IRQ_MBHC_RELEASE,
.mbhc_hs_ins_intr = MSM8X16_WCD_IRQ_MBHC_INSREM_DET1,
.mbhc_hs_rem_intr = MSM8X16_WCD_IRQ_MBHC_INSREM_DET,
.hph_left_ocp = MSM8X16_WCD_IRQ_HPHL_OCP,
.hph_right_ocp = MSM8X16_WCD_IRQ_HPHR_OCP,
static int msm8x16_wcd_codec_probe(struct snd_soc_codec *codec)
struct msm8x16_wcd_priv *msm8x16_wcd_
struct msm8x16_wcd *msm8x16_
dev_dbg(codec-&dev, "%s()\n", __func__);
msm8x16_wcd_priv = kzalloc(sizeof(struct msm8x16_wcd_priv), GFP_KERNEL);
if (!msm8x16_wcd_priv) {
dev_err(codec-&dev, "Failed to allocate private data\n");
return -ENOMEM;
for (i = 0; i & NUM_DECIMATORS; i++) {
tx_hpf_work[i].msm8x16_wcd = msm8x16_wcd_
tx_hpf_work[i].decimator = i + 1;
INIT_DELAYED_WORK(&tx_hpf_work[i].dwork,
tx_hpf_corner_freq_callback);
codec-&control_data = dev_get_drvdata(codec-&dev);
snd_soc_codec_set_drvdata(codec, msm8x16_wcd_priv);
msm8x16_wcd_priv-&codec =
/* codec resmgr module init */
msm8x16_wcd = codec-&control_
msm8x16_wcd-&dig_base = ioremap(MSM8X16_DIGITAL_CODEC_BASE_ADDR,
MSM8X16_DIGITAL_CODEC_REG_SIZE);
if (msm8x16_wcd-&dig_base == NULL) {
dev_err(codec-&dev, "%s ioremap failed\n", __func__);
kfree(msm8x16_wcd_priv);
return -ENOMEM;
msm8x16_wcd_priv-&spkdrv_reg =
wcd8x16_wcd_codec_find_regulator(codec-&control_data,
MSM89XX_VDD_SPKDRV_NAME);
msm8x16_wcd_priv-&pmic_rev = snd_soc_read(codec,
MSM8X16_WCD_A_DIGITAL_REVISION1);
msm8x16_wcd_priv-&codec_version = snd_soc_read(codec,
MSM8X16_WCD_A_DIGITAL_PERPH_SUBTYPE);
if (msm8x16_wcd_priv-&codec_version == CONGA) {
dev_dbg(codec-&dev, "%s :Conga REV: %d\n", __func__,
msm8x16_wcd_priv-&codec_version);
msm8x16_wcd_priv-&ext_spk_boost_set =
dev_dbg(codec-&dev, "%s :PMIC REV: %d\n", __func__,
msm8x16_wcd_priv-&pmic_rev);
* set to default boost option BOOST_SWITCH, user mixer path can change
* it to BOOST_ALWAYS or BOOST_BYPASS based on solution chosen.
msm8x16_wcd_priv-&boost_option = BOOST_SWITCH;
msm8x16_wcd_dt_parse_boost_info(codec);
msm8x16_wcd_set_boost_v(codec);
snd_soc_add_codec_controls(codec, impedance_detect_controls,
ARRAY_SIZE(impedance_detect_controls));
msm8x16_wcd_bringup(codec);
msm8x16_wcd_codec_init_reg(codec);
msm8x16_wcd_update_reg_defaults(codec);
wcd9xxx_spmi_set_codec(codec);
msm8x16_wcd_priv-&on_demand_list[ON_DEMAND_MICBIAS].supply =
wcd8x16_wcd_codec_find_regulator(
codec-&control_data,
on_demand_supply_name[ON_DEMAND_MICBIAS]);
atomic_set(&msm8x16_wcd_priv-&on_demand_list[ON_DEMAND_MICBIAS].ref, 0);
BLOCKING_INIT_NOTIFIER_HEAD(&msm8x16_wcd_priv-&notifier);
msm8x16_wcd_priv-&fw_data = kzalloc(sizeof(*(msm8x16_wcd_priv-&fw_data))
, GFP_KERNEL);
if (!msm8x16_wcd_priv-&fw_data) {
dev_err(codec-&dev, "Failed to allocate fw_data\n");
iounmap(msm8x16_wcd-&dig_base);
kfree(msm8x16_wcd_priv);
return -ENOMEM;
set_bit(WCD9XXX_MBHC_CAL, msm8x16_wcd_priv-&fw_data-&cal_bit);
ret = wcd_cal_create_hwdep(msm8x16_wcd_priv-&fw_data,
WCD9XXX_CODEC_HWDEP_NODE, codec);
if (ret & 0) {
dev_err(codec-&dev, "%s hwdep failed %d\n", __func__, ret);
iounmap(msm8x16_wcd-&dig_base);
kfree(msm8x16_wcd_priv-&fw_data);
kfree(msm8x16_wcd_priv);
wcd_mbhc_init(&msm8x16_wcd_priv-&mbhc, codec, &mbhc_cb, &intr_ids,
msm8x16_wcd_priv-&mclk_enabled =
msm8x16_wcd_priv-&clock_active =
msm8x16_wcd_priv-&config_mode_active =
/* Set initial MICBIAS voltage level */
msm8x16_wcd_set_micb_v(codec);
/* Set initial cap mode */
msm8x16_wcd_configure_cap(codec, false, false);
registered_codec =
modem_state_notifier =
subsys_notif_register_notifier("modem",
&modem_state_notifier_block);
if (!modem_state_notifier) {
dev_err(codec-&dev, "Failed to register modem state notifier\n"
iounmap(msm8x16_wcd-&dig_base);
kfree(msm8x16_wcd_priv-&fw_data);
kfree(msm8x16_wcd_priv);
registered_codec = NULL;
return -ENOMEM;
kernel/sound/soc/codecs/wcd-mbhc-v2.c
int wcd_mbhc_init(struct wcd_mbhc *mbhc, struct snd_soc_codec *codec,
const struct wcd_mbhc_cb *mbhc_cb,
const struct wcd_mbhc_intr *mbhc_cdc_intr_ids,
bool impedance_det_en)
int ret = 0;
int hph_swh = 0;
int gnd_swh = 0;
struct snd_soc_card *card = codec-&
const char *hph_switch = "qcom,msm-mbhc-hphl-swh";
const char *gnd_switch = "qcom,msm-mbhc-gnd-swh";
fb_notifier.notifier_call = fb_notifierier_
ret = fb_register_client(&fb_notifier);
printk( KERN_CRIT"%s: micbias Unable to register fb_notifier: %d\n", __func__,ret);
ret = of_property_read_u32(card-&dev-&of_node, hph_switch, &hph_swh);
if (ret) {
dev_err(card-&dev,
"%s: missing %s in dt node\n", __func__, hph_switch);
ret = of_property_read_u32(card-&dev-&of_node, gnd_switch, &gnd_swh);
if (ret) {
dev_err(card-&dev,
"%s: missing %s in dt node\n", __func__, gnd_switch);
mbhc-&in_swch_irq_handler =
mbhc-&current_plug = MBHC_PLUG_TYPE_NONE;
mbhc-&is_btn_press =
mbhc-&codec =
mbhc-&intr_ids = mbhc_cdc_intr_
mbhc-&impedance_detect = impedance_det_
mbhc-&hphl_swh = hph_
mbhc-&gnd_swh = gnd_
mbhc-&micbias_enable =
mbhc-&mbhc_cb = mbhc_
mbhc-&btn_press_intr =
mbhc-&is_hs_recording =
mbhc-&is_extn_cable =
mbhc-&skip_imped_detection =
if (mbhc-&intr_ids == NULL) {
pr_err("%s: Interrupt mapping not provided\n", __func__);
return -EINVAL;
if (mbhc-&headset_jack.jack == NULL) {
ret = snd_soc_jack_new(codec, "Headset Jack",
WCD_MBHC_JACK_MASK, &mbhc-&headset_jack);
if (ret) {
pr_err("%s: Failed to create new jack\n", __func__);
ret = snd_soc_jack_new(codec, "Button Jack",
WCD_MBHC_JACK_BUTTON_MASK,
&mbhc-&button_jack);
if (ret) {
pr_err("Failed to create new jack\n");
ret = snd_jack_set_key(mbhc-&button_jack.jack,
SND_JACK_BTN_0,
KEY_MEDIA);
if (ret) {
pr_err("%s: Failed to set code for btn-0\n",
__func__);
ret = snd_jack_set_key(mbhc-&button_jack.jack,
SND_JACK_BTN_1,
KEY_VOICECOMMAND);
if (ret) {
pr_err("%s: Failed to set code for btn-1:%d\n",
__func__, ret);
ret = snd_jack_set_key(mbhc-&button_jack.jack,
SND_JACK_BTN_2,
KEY_VOLUMEUP);
if (ret) {
pr_err("%s: Failed to set code for btn-2:%d\n",
__func__, ret);
ret = snd_jack_set_key(mbhc-&button_jack.jack,
SND_JACK_BTN_3,
KEY_VOLUMEDOWN);
if (ret) {
pr_err("%s: Failed to set code for btn-3:%d\n",
__func__, ret);
INIT_DELAYED_WORK(&mbhc-&mbhc_firmware_dwork,
wcd_mbhc_fw_read);
INIT_DELAYED_WORK(&mbhc-&mbhc_btn_dwork, wcd_btn_lpress_fn);
/* Register event notifier */
mbhc-&nblock.notifier_call = wcd_event_
ret = msm8x16_register_notifier(codec, &mbhc-&nblock);
if (ret) {
pr_err("%s: Failed to register notifier %d\n", __func__, ret);
init_waitqueue_head(&mbhc-&wait_btn_press);
mutex_init(&mbhc-&codec_resource_lock);
ret = wcd9xxx_spmi_request_irq(mbhc-&intr_ids-&mbhc_sw_intr,
wcd_mbhc_mech_plug_detect_irq,
"mbhc sw intr", mbhc);
if (ret) {
pr_err("%s: Failed to request irq %d, ret = %d\n", __func__,
mbhc-&intr_ids-&mbhc_sw_intr, ret);
goto err_mbhc_sw_
ret = wcd9xxx_spmi_request_irq(mbhc-&intr_ids-&mbhc_btn_press_intr,
wcd_mbhc_btn_press_handler,
"Button Press detect",
if (ret) {
pr_err("%s: Failed to request irq %d\n", __func__,
mbhc-&intr_ids-&mbhc_btn_press_intr);
goto err_btn_press_
ret = wcd9xxx_spmi_request_irq(mbhc-&intr_ids-&mbhc_btn_release_intr,
wcd_mbhc_release_handler,
"Button Release detect", mbhc);
if (ret) {
pr_err("%s: Failed to request irq %d\n", __func__,
mbhc-&intr_ids-&mbhc_btn_release_intr);
goto err_btn_release_
ret = wcd9xxx_spmi_request_irq(mbhc-&intr_ids-&mbhc_hs_ins_intr,
wcd_mbhc_hs_ins_irq,
"Elect Insert", mbhc);
if (ret) {
pr_err("%s: Failed to request irq %d\n", __func__,
mbhc-&intr_ids-&mbhc_hs_ins_intr);
goto err_mbhc_hs_ins_
wcd9xxx_spmi_disable_irq(mbhc-&intr_ids-&mbhc_hs_ins_intr);
ret = wcd9xxx_spmi_request_irq(mbhc-&intr_ids-&mbhc_hs_rem_intr,
wcd_mbhc_hs_rem_irq,
"Elect Remove", mbhc);
if (ret) {
pr_err("%s: Failed to request irq %d\n", __func__,
mbhc-&intr_ids-&mbhc_hs_rem_intr);
goto err_mbhc_hs_rem_
wcd9xxx_spmi_disable_irq(mbhc-&intr_ids-&mbhc_hs_rem_intr);
ret = wcd9xxx_spmi_request_irq(mbhc-&intr_ids-&hph_left_ocp,
wcd_mbhc_hphl_ocp_irq, "HPH_L OCP detect",
if (ret) {
pr_err("%s: Failed to request irq %d\n", __func__,
mbhc-&intr_ids-&hph_left_ocp);
goto err_hphl_ocp_
ret = wcd9xxx_spmi_request_irq(mbhc-&intr_ids-&hph_right_ocp,
wcd_mbhc_hphr_ocp_irq, "HPH_R OCP detect",
if (ret) {
pr_err("%s: Failed to request irq %d\n", __func__,
mbhc-&intr_ids-&hph_right_ocp);
goto err_hphr_ocp_
pr_debug("%s: leave ret %d\n", __func__, ret);
err_hphr_ocp_irq:
wcd9xxx_spmi_free_irq(mbhc-&intr_ids-&hph_left_ocp, mbhc);
err_hphl_ocp_irq:
wcd9xxx_spmi_free_irq(mbhc-&intr_ids-&mbhc_hs_rem_intr, mbhc);
err_mbhc_hs_rem_irq:
wcd9xxx_spmi_free_irq(mbhc-&intr_ids-&mbhc_hs_ins_intr, mbhc);
err_mbhc_hs_ins_irq:
wcd9xxx_spmi_free_irq(mbhc-&intr_ids-&mbhc_btn_release_intr, mbhc);
err_btn_release_irq:
wcd9xxx_spmi_free_irq(mbhc-&intr_ids-&mbhc_btn_press_intr, mbhc);
err_btn_press_irq:
wcd9xxx_spmi_free_irq(mbhc-&intr_ids-&mbhc_sw_intr, mbhc);
err_mbhc_sw_irq:
msm8x16_unregister_notifier(codec, &mbhc-&nblock);
mutex_destroy(&mbhc-&codec_resource_lock);
pr_debug("%s: leave ret %d\n", __func__, ret);
EXPORT_SYMBOL(wcd_mbhc_init);耳机检测中断函数static void wcd_mbhc_swch_irq_handler(struct wcd_mbhc *mbhc)
bool detection_
bool micbias1;
struct snd_soc_codec *codec = mbhc-&
pr_debug("%s: enter\n", __func__);
WCD_MBHC_RSC_LOCK(mbhc);
mbhc-&in_swch_irq_handler =
/* cancel pending button press */
if (wcd_cancel_btn_work(mbhc))
pr_debug("%s: button press is canceled\n", __func__);
detection_type = (snd_soc_read(codec,
MSM8X16_WCD_A_ANALOG_MBHC_DET_CTL_1)) & 0x20;
/* Set the detection type appropriately */
snd_soc_update_bits(codec, MSM8X16_WCD_A_ANALOG_MBHC_DET_CTL_1,
0x20, (!detection_type && 5));
pr_debug("%s: mbhc-&current_plug: %d detection_type: %d\n", __func__,
mbhc-&current_plug, detection_type);
wcd_cancel_hs_detect_plug(mbhc, &mbhc-&correct_plug_swch);
micbias1 = (snd_soc_read(codec, MSM8X16_WCD_A_ANALOG_MICB_1_EN) & 0x80);
if ((mbhc-&current_plug == MBHC_PLUG_TYPE_NONE) &&
detection_type) {
/* Make sure MASTER_BIAS_CTL is enabled */
snd_soc_update_bits(codec,
MSM8X16_WCD_A_ANALOG_MASTER_BIAS_CTL,
0x30, 0x30);
snd_soc_update_bits(codec,
MSM8X16_WCD_A_ANALOG_MICB_1_EN,
0x04, 0x04);
if (!mbhc-&mbhc_cfg-&hs_ext_micbias)
/* Enable Tx2 RBias if the headset
* is using internal micbias*/
snd_soc_update_bits(codec,
MSM8X16_WCD_A_ANALOG_MICB_1_INT_RBIAS,
0x10, 0x10);
/* Remove pull down on MIC BIAS2 */
snd_soc_update_bits(codec,
MSM8X16_WCD_A_ANALOG_MICB_2_EN,
0x20, 0x00);
/* Enable HW FSM */
snd_soc_update_bits(codec,
MSM8X16_WCD_A_ANALOG_MBHC_FSM_CTL,
0x80, 0x80);
/* Apply trim if needed on the device */
if (mbhc-&mbhc_cb && mbhc-&mbhc_cb-&trim_btn_reg)
mbhc-&mbhc_cb-&trim_btn_reg(codec);
/* Enable external voltage source to micbias if present */
if (mbhc-&mbhc_cb && mbhc-&mbhc_cb-&enable_mb_source)
mbhc-&mbhc_cb-&enable_mb_source(codec, true);
mbhc-&btn_press_intr =
wcd_mbhc_detect_plug_type(mbhc);
} else if ((mbhc-&current_plug != MBHC_PLUG_TYPE_NONE)
&& !detection_type) {
/* Disable external voltage source to micbias if present */
if (mbhc-&mbhc_cb && mbhc-&mbhc_cb-&enable_mb_source)
mbhc-&mbhc_cb-&enable_mb_source(codec, false);
/* Disable HW FSM */
snd_soc_update_bits(codec,
MSM8X16_WCD_A_ANALOG_MBHC_FSM_CTL,
0xB0, 0x00);
snd_soc_update_bits(codec,
MSM8X16_WCD_A_ANALOG_MICB_1_EN,
0x04, 0x00);
if (mbhc-&mbhc_cb && mbhc-&mbhc_cb-&set_cap_mode)
mbhc-&mbhc_cb-&set_cap_mode(codec, micbias1, false);
mbhc-&btn_press_intr =
if (mbhc-&current_plug == MBHC_PLUG_TYPE_HEADPHONE) {
wcd_mbhc_report_plug(mbhc, 0, SND_JACK_HEADPHONE);
} else if (mbhc-&current_plug == MBHC_PLUG_TYPE_GND_MIC_SWAP) {
wcd_mbhc_report_plug(mbhc, 0, SND_JACK_UNSUPPORTED);
} else if (mbhc-&current_plug == MBHC_PLUG_TYPE_HEADSET) {
/* make sure to turn off Rbias */
snd_soc_update_bits(codec,
MSM8X16_WCD_A_ANALOG_MICB_1_INT_RBIAS,
0x18, 0x08);
snd_soc_update_bits(codec,
MSM8X16_WCD_A_ANALOG_MICB_2_EN,
0x20, 0x20);
wcd9xxx_spmi_disable_irq(
mbhc-&intr_ids-&mbhc_hs_rem_intr);
wcd9xxx_spmi_disable_irq(
mbhc-&intr_ids-&mbhc_hs_ins_intr);
snd_soc_update_bits(codec,
MSM8X16_WCD_A_ANALOG_MBHC_DET_CTL_1,
0x01, 0x01);
snd_soc_update_bits(codec,
MSM8X16_WCD_A_ANALOG_MBHC_DET_CTL_2,
0x06, 0x00);
wcd_mbhc_report_plug(mbhc, 0, SND_JACK_HEADSET);
} else if (mbhc-&current_plug == MBHC_PLUG_TYPE_HIGH_HPH) {
mbhc-&is_extn_cable =
wcd9xxx_spmi_disable_irq(
mbhc-&intr_ids-&mbhc_hs_rem_intr);
wcd9xxx_spmi_disable_irq(
mbhc-&intr_ids-&mbhc_hs_ins_intr);
snd_soc_update_bits(codec,
MSM8X16_WCD_A_ANALOG_MBHC_DET_CTL_1,
0x01, 0x01);
snd_soc_update_bits(codec,
MSM8X16_WCD_A_ANALOG_MBHC_DET_CTL_2,
0x06, 0x00);
wcd_mbhc_report_plug(mbhc, 0, SND_JACK_LINEOUT);
} else if (!detection_type) {
/* Disable external voltage source to micbias if present */
if (mbhc-&mbhc_cb && mbhc-&mbhc_cb-&enable_mb_source)
mbhc-&mbhc_cb-&enable_mb_source(codec, false);
/* Disable HW FSM */
snd_soc_update_bits(codec,
MSM8X16_WCD_A_ANALOG_MBHC_FSM_CTL,
0xB0, 0x00);
mbhc-&in_swch_irq_handler =
WCD_MBHC_RSC_UNLOCK(mbhc);
pr_debug("%s: leave\n", __func__);
static irqreturn_t wcd_mbhc_mech_plug_detect_irq(int irq, void *data)
int r = IRQ_HANDLED;
struct wcd_mbhc *mbhc =
pr_debug("%s: enter\n", __func__);
if (unlikely(wcd9xxx_spmi_lock_sleep() == false)) {
pr_warn("%s: failed to hold suspend\n", __func__);
r = IRQ_NONE;
/* Call handler */
wcd_mbhc_swch_irq_handler(mbhc);
wcd9xxx_spmi_unlock_sleep();
pr_debug("%s: leave %d\n", __func__, r);
}经过一系列的检测,判断是headset,headphones等,如果是headphones,最终通过wcd_mbhc_jack_report将数据汇报上去。
static void wcd_mbhc_jack_report(struct wcd_mbhc *mbhc,
struct snd_soc_jack *jack, int status, int mask)
snd_soc_jack_report_no_dapm(jack, status, mask);
void snd_soc_jack_report_no_dapm(struct snd_soc_jack *jack, int status,
jack-&status &= ~
jack-&status |= status &
snd_jack_report(jack-&jack, jack-&status);
EXPORT_SYMBOL_GPL(snd_soc_jack_report_no_dapm);
void snd_jack_report(struct snd_jack *jack, int status)
if (!jack)
for (i = 0; i & ARRAY_SIZE(jack-&key); i++) {
int testbit = SND_JACK_BTN_0 &&
if (jack-&type & testbit)
input_report_key(jack-&input_dev, jack-&key[i],
status & testbit);
for (i = 0; i & ARRAY_SIZE(jack_switch_types); i++) {
int testbit = 1 &&
if (jack-&type & testbit)
input_report_switch(jack-&input_dev,
jack_switch_types[i],
status & testbit);
input_sync(jack-&input_dev);
EXPORT_SYMBOL(snd_jack_report);最终汇报上去的有效数据是5   2   1 (插头类型 耳机信号 值插入)
 0(同步)
当然也可以手工通过sendevent 发送事件,systemui就能显示耳机接入的图标
getevent -i获取Headset Jack对应的input,假设是/dev/input/event2,
则可以通过如下方法模拟耳机接入和拔出
sendevent /dev/input/event2 5 2 1
sendevent /dev/input/event2 0 0 0
或者拨出耳机
sendevent /dev/input/event2 5 2 0
sendevent /dev/input/event2 0 0 0这种方法只有成功检测到了耳机后才有效,可能还存在其他的机制。
关于线控耳机原理可参考
没有更多推荐了,

我要回帖

更多关于 一阶高通滤波器电路图 的文章

 

随机推荐