Loading Documentation/devicetree/bindings/sound/qcom-audio-dev.txt +2 −0 Original line number Diff line number Diff line Loading @@ -598,6 +598,7 @@ Optional Properties: capacitor mode. - qcom,msm-micbias2-ext-cap : Boolean. Enable micbias2 external capacitor mode. - qcom,msm-spk-ext-pa : GPIO which enables external speaker pa. Example: Loading @@ -612,6 +613,7 @@ Example: qcom,msm-mbhc-gnd-swh = <0>; qcom,msm-hs-micbias-type = "internal"; qcom,cdc-us-euro-gpios = <&msmgpio 120 0>; qcom,msm-spk-ext-pa = <&msm_gpio 0 0>; qcom,audio-routing = "RX_BIAS", "MCLK", "INT_LDO_H", "MCLK", Loading sound/soc/codecs/msm8x16-wcd.c +53 −0 Original line number Diff line number Diff line Loading @@ -196,6 +196,16 @@ static void *modem_state_notifier; static struct snd_soc_codec *registered_codec; void msm8x16_wcd_spk_ext_pa_cb( int (*codec_spk_ext_pa)(struct snd_soc_codec *codec, int enable), struct snd_soc_codec *codec) { struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec); pr_debug("%s: Enter\n", __func__); msm8x16_wcd->codec_spk_ext_pa_cb = codec_spk_ext_pa; } static void msm8x16_wcd_compute_impedance(s16 l, s16 r, uint32_t *zl, uint32_t *zr, bool high) { Loading Loading @@ -1522,6 +1532,10 @@ static const char * const adc2_mux_text[] = { "ZERO", "INP2", "INP3" }; static const char * const ext_spk_text[] = { "Off", "On" }; static const char * const rdac2_mux_text[] = { "ZERO", "RX2", "RX1" }; Loading @@ -1533,6 +1547,9 @@ static const char * const iir_inp1_text[] = { static const struct soc_enum adc2_enum = SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(adc2_mux_text), adc2_mux_text); static const struct soc_enum ext_spk_enum = SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(ext_spk_text), ext_spk_text); /* RX1 MIX1 */ static const struct soc_enum rx_mix1_inp1_chain_enum = SOC_ENUM_SINGLE(MSM8X16_WCD_A_CDC_CONN_RX1_B1_CTL, Loading Loading @@ -1603,6 +1620,9 @@ static const struct soc_enum iir2_inp1_mux_enum = SOC_ENUM_SINGLE(MSM8X16_WCD_A_CDC_CONN_EQ2_B1_CTL, 0, 6, iir_inp1_text); static const struct snd_kcontrol_new ext_spk_mux = SOC_DAPM_ENUM_VIRT("Ext Spk Switch Mux", ext_spk_enum); static const struct snd_kcontrol_new rx_mix1_inp1_mux = SOC_DAPM_ENUM("RX1 MIX1 INP1 Mux", rx_mix1_inp1_chain_enum); Loading Loading @@ -2773,6 +2793,10 @@ static const struct snd_soc_dapm_route audio_map[] = { {"HEADPHONE", NULL, "HPHL PA"}, {"HEADPHONE", NULL, "HPHR PA"}, {"Ext Spk", NULL, "Ext Spk Switch"}, {"Ext Spk Switch", "On", "HPHL PA"}, {"Ext Spk Switch", "On", "HPHR PA"}, {"HPHL PA", NULL, "HPHL"}, {"HPHR PA", NULL, "HPHR"}, {"HPHL", "Switch", "HPHL DAC"}, Loading Loading @@ -3207,6 +3231,30 @@ static int msm8x16_wcd_codec_enable_rx_chain(struct snd_soc_dapm_widget *w, return 0; } static int msm8x16_wcd_codec_enable_spk_ext_pa(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { struct snd_soc_codec *codec = w->codec; struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec); dev_dbg(codec->dev, "%s: %s event = %d\n", __func__, w->name, event); switch (event) { case SND_SOC_DAPM_POST_PMU: dev_dbg(w->codec->dev, "%s: enable external speaker PA\n", __func__); if (msm8x16_wcd->codec_spk_ext_pa_cb) msm8x16_wcd->codec_spk_ext_pa_cb(codec, 1); break; case SND_SOC_DAPM_PRE_PMD: dev_dbg(w->codec->dev, "%s: enable external speaker PA\n", __func__); if (msm8x16_wcd->codec_spk_ext_pa_cb) msm8x16_wcd->codec_spk_ext_pa_cb(codec, 0); break; } return 0; } static int msm8x16_wcd_codec_enable_ear_pa(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { Loading Loading @@ -3280,6 +3328,8 @@ static const struct snd_soc_dapm_widget msm8x16_wcd_dapm_widgets[] = { SND_SOC_DAPM_SUPPLY("INT_LDO_H", SND_SOC_NOPM, 1, 0, NULL, 0), SND_SOC_DAPM_SPK("Ext Spk", msm8x16_wcd_codec_enable_spk_ext_pa), SND_SOC_DAPM_OUTPUT("HEADPHONE"), SND_SOC_DAPM_PGA_E("HPHL PA", MSM8X16_WCD_A_ANALOG_RX_HPH_CNP_EN, 5, 0, NULL, 0, Loading Loading @@ -3326,6 +3376,9 @@ static const struct snd_soc_dapm_widget msm8x16_wcd_dapm_widgets[] = { msm89xx_wcd_codec_enable_vdd_spkr, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_VIRT_MUX("Ext Spk Switch", SND_SOC_NOPM, 0, 0, &ext_spk_mux), SND_SOC_DAPM_MIXER("RX1 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0), SND_SOC_DAPM_MIXER("RX2 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0), Loading sound/soc/codecs/msm8x16-wcd.h +6 −1 Original line number Diff line number Diff line /* Copyright (c) 2014, The Linux Foundation. All rights reserved. /* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -160,6 +160,7 @@ struct msm8916_asoc_mach_data { int codec_type; int ext_pa; int us_euro_gpio; int spk_ext_pa_gpio; int mclk_freq; int lb_mode; u8 micbias1_cap_mode; Loading Loading @@ -238,6 +239,7 @@ struct msm8x16_wcd_priv { /* cal info for codec */ struct fw_info *fw_data; struct blocking_notifier_head notifier; int (*codec_spk_ext_pa_cb)(struct snd_soc_codec *codec, int enable); }; Loading @@ -255,5 +257,8 @@ extern int msm8x16_register_notifier(struct snd_soc_codec *codec, extern int msm8x16_unregister_notifier(struct snd_soc_codec *codec, struct notifier_block *nblock); extern void msm8x16_wcd_spk_ext_pa_cb( int (*codec_spk_ext_pa)(struct snd_soc_codec *codec, int enable), struct snd_soc_codec *codec); #endif sound/soc/msm/msm8x16.c +36 −2 Original line number Diff line number Diff line /* Copyright (c) 2014, The Linux Foundation. All rights reserved. /* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -276,6 +276,24 @@ static int msm_auxpcm_be_params_fixup(struct snd_soc_pcm_runtime *rtd, return 0; } static int enable_spk_ext_pa(struct snd_soc_codec *codec, int enable) { struct snd_soc_card *card = codec->card; struct msm8916_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card); if (!gpio_is_valid(pdata->spk_ext_pa_gpio)) { pr_err("%s: Invalid gpio: %d\n", __func__, pdata->spk_ext_pa_gpio); return false; } pr_debug("%s: %s external speaker PA\n", __func__, enable ? "Enable" : "Disable"); gpio_set_value_cansleep(pdata->spk_ext_pa_gpio, enable); return 0; } static int msm_pri_rx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params) { Loading Loading @@ -1375,6 +1393,8 @@ static int msm_audrx_init(struct snd_soc_pcm_runtime *rtd) snd_soc_dapm_sync(dapm); msm8x16_wcd_spk_ext_pa_cb(enable_spk_ext_pa, codec); mbhc_cfg.calibration = def_msm8x16_wcd_mbhc_cal(); if (mbhc_cfg.calibration) { ret = msm8x16_wcd_hs_detect(codec, &mbhc_cfg); Loading Loading @@ -2491,6 +2511,7 @@ static int msm8x16_asoc_machine_probe(struct platform_device *pdev) const char *hs_micbias_type = "qcom,msm-hs-micbias-type"; const char *ext_pa = "qcom,msm-ext-pa"; const char *mclk = "qcom,msm-mclk-freq"; const char *spk_ext_pa = "qcom,msm-spk-ext-pa"; const char *ptr = NULL; const char *type = NULL; const char *ext_pa_str = NULL; Loading Loading @@ -2548,11 +2569,24 @@ static int msm8x16_asoc_machine_probe(struct platform_device *pdev) ret = of_property_read_u32(pdev->dev.of_node, mclk, &id); if (ret) { dev_err(&pdev->dev, "%s: missing %s in dt node\n", __func__, card_dev_id); "%s: missing %s in dt node\n", __func__, mclk); id = DEFAULT_MCLK_RATE; } pdata->mclk_freq = id; pdata->spk_ext_pa_gpio = of_get_named_gpio(pdev->dev.of_node, spk_ext_pa, 0); if (pdata->spk_ext_pa_gpio < 0) { dev_dbg(&pdev->dev, "%s: missing %s in dt node\n", __func__, spk_ext_pa); } else { if (!gpio_is_valid(pdata->spk_ext_pa_gpio)) { pr_err("%s: Invalid external speaker gpio: %d", __func__, pdata->spk_ext_pa_gpio); return -EINVAL; } } ret = of_property_read_string(pdev->dev.of_node, codec_type, &ptr); if (ret) { dev_err(&pdev->dev, Loading Loading
Documentation/devicetree/bindings/sound/qcom-audio-dev.txt +2 −0 Original line number Diff line number Diff line Loading @@ -598,6 +598,7 @@ Optional Properties: capacitor mode. - qcom,msm-micbias2-ext-cap : Boolean. Enable micbias2 external capacitor mode. - qcom,msm-spk-ext-pa : GPIO which enables external speaker pa. Example: Loading @@ -612,6 +613,7 @@ Example: qcom,msm-mbhc-gnd-swh = <0>; qcom,msm-hs-micbias-type = "internal"; qcom,cdc-us-euro-gpios = <&msmgpio 120 0>; qcom,msm-spk-ext-pa = <&msm_gpio 0 0>; qcom,audio-routing = "RX_BIAS", "MCLK", "INT_LDO_H", "MCLK", Loading
sound/soc/codecs/msm8x16-wcd.c +53 −0 Original line number Diff line number Diff line Loading @@ -196,6 +196,16 @@ static void *modem_state_notifier; static struct snd_soc_codec *registered_codec; void msm8x16_wcd_spk_ext_pa_cb( int (*codec_spk_ext_pa)(struct snd_soc_codec *codec, int enable), struct snd_soc_codec *codec) { struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec); pr_debug("%s: Enter\n", __func__); msm8x16_wcd->codec_spk_ext_pa_cb = codec_spk_ext_pa; } static void msm8x16_wcd_compute_impedance(s16 l, s16 r, uint32_t *zl, uint32_t *zr, bool high) { Loading Loading @@ -1522,6 +1532,10 @@ static const char * const adc2_mux_text[] = { "ZERO", "INP2", "INP3" }; static const char * const ext_spk_text[] = { "Off", "On" }; static const char * const rdac2_mux_text[] = { "ZERO", "RX2", "RX1" }; Loading @@ -1533,6 +1547,9 @@ static const char * const iir_inp1_text[] = { static const struct soc_enum adc2_enum = SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(adc2_mux_text), adc2_mux_text); static const struct soc_enum ext_spk_enum = SOC_ENUM_SINGLE(0, 0, ARRAY_SIZE(ext_spk_text), ext_spk_text); /* RX1 MIX1 */ static const struct soc_enum rx_mix1_inp1_chain_enum = SOC_ENUM_SINGLE(MSM8X16_WCD_A_CDC_CONN_RX1_B1_CTL, Loading Loading @@ -1603,6 +1620,9 @@ static const struct soc_enum iir2_inp1_mux_enum = SOC_ENUM_SINGLE(MSM8X16_WCD_A_CDC_CONN_EQ2_B1_CTL, 0, 6, iir_inp1_text); static const struct snd_kcontrol_new ext_spk_mux = SOC_DAPM_ENUM_VIRT("Ext Spk Switch Mux", ext_spk_enum); static const struct snd_kcontrol_new rx_mix1_inp1_mux = SOC_DAPM_ENUM("RX1 MIX1 INP1 Mux", rx_mix1_inp1_chain_enum); Loading Loading @@ -2773,6 +2793,10 @@ static const struct snd_soc_dapm_route audio_map[] = { {"HEADPHONE", NULL, "HPHL PA"}, {"HEADPHONE", NULL, "HPHR PA"}, {"Ext Spk", NULL, "Ext Spk Switch"}, {"Ext Spk Switch", "On", "HPHL PA"}, {"Ext Spk Switch", "On", "HPHR PA"}, {"HPHL PA", NULL, "HPHL"}, {"HPHR PA", NULL, "HPHR"}, {"HPHL", "Switch", "HPHL DAC"}, Loading Loading @@ -3207,6 +3231,30 @@ static int msm8x16_wcd_codec_enable_rx_chain(struct snd_soc_dapm_widget *w, return 0; } static int msm8x16_wcd_codec_enable_spk_ext_pa(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { struct snd_soc_codec *codec = w->codec; struct msm8x16_wcd_priv *msm8x16_wcd = snd_soc_codec_get_drvdata(codec); dev_dbg(codec->dev, "%s: %s event = %d\n", __func__, w->name, event); switch (event) { case SND_SOC_DAPM_POST_PMU: dev_dbg(w->codec->dev, "%s: enable external speaker PA\n", __func__); if (msm8x16_wcd->codec_spk_ext_pa_cb) msm8x16_wcd->codec_spk_ext_pa_cb(codec, 1); break; case SND_SOC_DAPM_PRE_PMD: dev_dbg(w->codec->dev, "%s: enable external speaker PA\n", __func__); if (msm8x16_wcd->codec_spk_ext_pa_cb) msm8x16_wcd->codec_spk_ext_pa_cb(codec, 0); break; } return 0; } static int msm8x16_wcd_codec_enable_ear_pa(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { Loading Loading @@ -3280,6 +3328,8 @@ static const struct snd_soc_dapm_widget msm8x16_wcd_dapm_widgets[] = { SND_SOC_DAPM_SUPPLY("INT_LDO_H", SND_SOC_NOPM, 1, 0, NULL, 0), SND_SOC_DAPM_SPK("Ext Spk", msm8x16_wcd_codec_enable_spk_ext_pa), SND_SOC_DAPM_OUTPUT("HEADPHONE"), SND_SOC_DAPM_PGA_E("HPHL PA", MSM8X16_WCD_A_ANALOG_RX_HPH_CNP_EN, 5, 0, NULL, 0, Loading Loading @@ -3326,6 +3376,9 @@ static const struct snd_soc_dapm_widget msm8x16_wcd_dapm_widgets[] = { msm89xx_wcd_codec_enable_vdd_spkr, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_VIRT_MUX("Ext Spk Switch", SND_SOC_NOPM, 0, 0, &ext_spk_mux), SND_SOC_DAPM_MIXER("RX1 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0), SND_SOC_DAPM_MIXER("RX2 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0), Loading
sound/soc/codecs/msm8x16-wcd.h +6 −1 Original line number Diff line number Diff line /* Copyright (c) 2014, The Linux Foundation. All rights reserved. /* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -160,6 +160,7 @@ struct msm8916_asoc_mach_data { int codec_type; int ext_pa; int us_euro_gpio; int spk_ext_pa_gpio; int mclk_freq; int lb_mode; u8 micbias1_cap_mode; Loading Loading @@ -238,6 +239,7 @@ struct msm8x16_wcd_priv { /* cal info for codec */ struct fw_info *fw_data; struct blocking_notifier_head notifier; int (*codec_spk_ext_pa_cb)(struct snd_soc_codec *codec, int enable); }; Loading @@ -255,5 +257,8 @@ extern int msm8x16_register_notifier(struct snd_soc_codec *codec, extern int msm8x16_unregister_notifier(struct snd_soc_codec *codec, struct notifier_block *nblock); extern void msm8x16_wcd_spk_ext_pa_cb( int (*codec_spk_ext_pa)(struct snd_soc_codec *codec, int enable), struct snd_soc_codec *codec); #endif
sound/soc/msm/msm8x16.c +36 −2 Original line number Diff line number Diff line /* Copyright (c) 2014, The Linux Foundation. All rights reserved. /* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -276,6 +276,24 @@ static int msm_auxpcm_be_params_fixup(struct snd_soc_pcm_runtime *rtd, return 0; } static int enable_spk_ext_pa(struct snd_soc_codec *codec, int enable) { struct snd_soc_card *card = codec->card; struct msm8916_asoc_mach_data *pdata = snd_soc_card_get_drvdata(card); if (!gpio_is_valid(pdata->spk_ext_pa_gpio)) { pr_err("%s: Invalid gpio: %d\n", __func__, pdata->spk_ext_pa_gpio); return false; } pr_debug("%s: %s external speaker PA\n", __func__, enable ? "Enable" : "Disable"); gpio_set_value_cansleep(pdata->spk_ext_pa_gpio, enable); return 0; } static int msm_pri_rx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params) { Loading Loading @@ -1375,6 +1393,8 @@ static int msm_audrx_init(struct snd_soc_pcm_runtime *rtd) snd_soc_dapm_sync(dapm); msm8x16_wcd_spk_ext_pa_cb(enable_spk_ext_pa, codec); mbhc_cfg.calibration = def_msm8x16_wcd_mbhc_cal(); if (mbhc_cfg.calibration) { ret = msm8x16_wcd_hs_detect(codec, &mbhc_cfg); Loading Loading @@ -2491,6 +2511,7 @@ static int msm8x16_asoc_machine_probe(struct platform_device *pdev) const char *hs_micbias_type = "qcom,msm-hs-micbias-type"; const char *ext_pa = "qcom,msm-ext-pa"; const char *mclk = "qcom,msm-mclk-freq"; const char *spk_ext_pa = "qcom,msm-spk-ext-pa"; const char *ptr = NULL; const char *type = NULL; const char *ext_pa_str = NULL; Loading Loading @@ -2548,11 +2569,24 @@ static int msm8x16_asoc_machine_probe(struct platform_device *pdev) ret = of_property_read_u32(pdev->dev.of_node, mclk, &id); if (ret) { dev_err(&pdev->dev, "%s: missing %s in dt node\n", __func__, card_dev_id); "%s: missing %s in dt node\n", __func__, mclk); id = DEFAULT_MCLK_RATE; } pdata->mclk_freq = id; pdata->spk_ext_pa_gpio = of_get_named_gpio(pdev->dev.of_node, spk_ext_pa, 0); if (pdata->spk_ext_pa_gpio < 0) { dev_dbg(&pdev->dev, "%s: missing %s in dt node\n", __func__, spk_ext_pa); } else { if (!gpio_is_valid(pdata->spk_ext_pa_gpio)) { pr_err("%s: Invalid external speaker gpio: %d", __func__, pdata->spk_ext_pa_gpio); return -EINVAL; } } ret = of_property_read_string(pdev->dev.of_node, codec_type, &ptr); if (ret) { dev_err(&pdev->dev, Loading