audio: auge: add lower power mode for PDM & vad [1/1]
authorXing Wang <xing.wang@amlogic.com>
Sat, 19 Jan 2019 08:05:46 +0000 (16:05 +0800)
committerTao Zeng <tao.zeng@amlogic.com>
Wed, 8 May 2019 01:47:18 +0000 (18:47 -0700)
PD#SWPL-3825

Problem:
VAD & PDM works in 24m clks for lowpower mode when in deep suspend

Solution:
support VAD & PDM in 24m sysclk, 768k dclk

Verify:
x301

Change-Id: Ic363337ee9b0eba0f890ae62b9e0cb6bb54dcd6a
Signed-off-by: Xing Wang <xing.wang@amlogic.com>
17 files changed:
arch/arm/boot/dts/amlogic/tl1_t962x2_t309.dts
arch/arm/boot/dts/amlogic/tl1_t962x2_x301_1g.dts
arch/arm/boot/dts/amlogic/tl1_t962x2_x301_2g.dts
arch/arm64/boot/dts/amlogic/tl1_t962x2_x301_1g.dts
arch/arm64/boot/dts/amlogic/tl1_t962x2_x301_2g.dts
sound/soc/amlogic/auge/pdm.c
sound/soc/amlogic/auge/pdm.h
sound/soc/amlogic/auge/pdm_hw.c
sound/soc/amlogic/auge/pdm_hw.h
sound/soc/amlogic/auge/regs.h
sound/soc/amlogic/auge/sm1,clocks.c
sound/soc/amlogic/auge/tl1,clocks.c
sound/soc/amlogic/auge/tm2,clocks.c
sound/soc/amlogic/auge/vad.c
sound/soc/amlogic/auge/vad.h
sound/soc/amlogic/auge/vad_hw.c
sound/soc/amlogic/auge/vad_hw.h

index b0db115..79a8b40 100644 (file)
                pinctrl-0 = <&spdifout_a>;
                pinctrl-1 = <&spdifout_a_mute>;
 
-
                /*
                 * whether do asrc for pcm and resample a or b
                 * if raw data, asrc is disabled automatically
index f21e445..418b7b6 100644 (file)
                 */
                level = <1>;
 
-               status = "disabled";
+               status = "okay";
        };
 
        loopbacka:loopback@0 {
index 3a38a32..6b2e45e 100644 (file)
                 */
                level = <1>;
 
-               status = "disabled";
+               status = "okay";
        };
 
        loopbacka:loopback@0 {
index cf97a08..9f9b053 100644 (file)
                 */
                level = <1>;
 
-               status = "disabled";
+               status = "okay";
        };
 
        loopbacka:loopback@0 {
index d7e8e2f..9b3a9cf 100644 (file)
                 */
                level = <1>;
 
-               status = "disabled";
+               status = "okay";
        };
 
        loopbacka:loopback@0 {
index 3debb34..bc90f43 100644 (file)
@@ -28,6 +28,8 @@
 #include <sound/soc.h>
 #include <sound/tlv.h>
 
+#include <linux/amlogic/pm.h>
+
 #include "pdm.h"
 #include "pdm_hw.h"
 #include "pdm_match_table.c"
@@ -230,6 +232,100 @@ static int pdm_bypass_set_enum(
        return 0;
 }
 
+static const char *const pdm_lowpower_texts[] = {
+       "PDM Normal Mode",
+       "PDM Low Power Mode",
+};
+
+static const struct soc_enum pdm_lowpower_enum =
+       SOC_ENUM_SINGLE(SND_SOC_NOPM, 0, ARRAY_SIZE(pdm_lowpower_texts),
+                       pdm_lowpower_texts);
+
+static void pdm_set_lowpower_mode(struct aml_pdm *p_pdm, bool isLowPower)
+{
+       if (p_pdm->isLowPower == isLowPower)
+               return;
+
+       p_pdm->isLowPower = isLowPower;
+
+       if (p_pdm->clk_on) {
+               int osr, filter_mode, dclk_idx;
+
+               if (p_pdm->isLowPower) {
+                       /* dclk for 768k */
+                       dclk_idx = 2;
+
+                       pr_info("%s force pdm sysclk to 24m, dclk 768k\n",
+                               __func__);
+               } else
+                       dclk_idx = p_pdm->dclk_idx;
+
+               clk_set_rate(p_pdm->clk_pdm_dclk,
+                       pdm_dclkidx2rate(dclk_idx));
+
+               /* filter for pdm */
+               osr = pdm_get_ors(dclk_idx, p_pdm->rate);
+               if (!osr)
+                       osr = 192;
+
+               filter_mode = p_pdm->isLowPower ? 4 : p_pdm->filter_mode;
+               aml_pdm_filter_ctrl(osr, filter_mode);
+
+               /* update sample count */
+               pdm_set_channel_ctrl(
+                       pdm_get_sample_count(
+                               p_pdm->isLowPower,
+                               dclk_idx)
+                       );
+
+               /* check to set pdm sysclk */
+               pdm_force_sysclk_to_oscin(p_pdm->isLowPower);
+
+               pr_info("\n%s, pdm_sysclk:%lu pdm_dclk:%lu, dclk_srcpll:%lu\n",
+                       __func__,
+                       clk_get_rate(p_pdm->clk_pdm_sysclk),
+                       clk_get_rate(p_pdm->clk_pdm_dclk),
+                       clk_get_rate(p_pdm->dclk_srcpll));
+
+               /* Check to set vad for Low Power */
+               if (vad_pdm_is_running())
+                       vad_set_lowerpower_mode(p_pdm->isLowPower);
+       }
+}
+
+static int pdm_lowpower_get_enum(
+       struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
+       struct aml_pdm *p_pdm = dev_get_drvdata(component->dev);
+
+       if (!p_pdm)
+               return 0;
+
+       ucontrol->value.enumerated.item[0] = p_pdm->isLowPower;
+
+       return 0;
+}
+
+
+static int pdm_lowpower_set_enum(
+       struct snd_kcontrol *kcontrol,
+       struct snd_ctl_elem_value *ucontrol)
+{
+       struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
+       struct aml_pdm *p_pdm = dev_get_drvdata(component->dev);
+       bool isLowPower;
+
+       if (!p_pdm)
+               return 0;
+
+       isLowPower = (bool)ucontrol->value.enumerated.item[0];
+       pdm_set_lowpower_mode(p_pdm, isLowPower);
+
+       return 0;
+}
+
 static const char *const pdm_train_texts[] = {
        "Disabled",
        "Enable",
@@ -293,6 +389,11 @@ static const struct snd_kcontrol_new snd_pdm_controls[] = {
                     pdm_dclk_get_enum,
                     pdm_dclk_set_enum),
 
+       SOC_ENUM_EXT("PDM Low Power mode",
+                       pdm_lowpower_enum,
+                       pdm_lowpower_get_enum,
+                       pdm_lowpower_set_enum),
+
        SOC_ENUM_EXT("PDM Train",
                     pdm_train_enum,
                     pdm_train_get_enum,
@@ -766,7 +867,7 @@ static int aml_pdm_dai_prepare(
        if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
                struct toddr *to = p_pdm->tddr;
                struct toddr_fmt fmt;
-               unsigned int osr = 192, filter_mode;
+               unsigned int osr = 192, filter_mode, dclk_idx;
                struct pdm_info info;
 
                /* to ddr pdmin */
@@ -781,29 +882,41 @@ static int aml_pdm_dai_prepare(
                aml_toddr_set_format(to, &fmt);
                aml_toddr_set_fifos(to, 0x40);
 
-               info.bitdepth   = bitwidth;
-               info.channels   = runtime->channels;
-               info.lane_masks = p_pdm->lane_mask_in;
-               info.dclk_idx   = p_pdm->dclk_idx;
-               info.bypass     = p_pdm->bypass;
-               info.sample_count = pdm_get_sample_count(p_pdm->isLowPower,
-                               p_pdm->dclk_idx);
-               aml_pdm_ctrl(&info);
-
-               filter_mode = p_pdm->filter_mode;
+               /* force pdm sysclk to 24m */
+               if (p_pdm->isLowPower) {
+                       /* dclk for 768k */
+                       dclk_idx = 2;
+                       filter_mode = 4;
+                       pdm_force_sysclk_to_oscin(true);
+                       if (vad_pdm_is_running())
+                               vad_set_lowerpower_mode(true);
+
+               } else {
+                       dclk_idx = p_pdm->dclk_idx;
+                       filter_mode = p_pdm->filter_mode;
+               }
 
                /* filter for pdm */
-               osr = pdm_get_ors(p_pdm->dclk_idx, runtime->rate);
+               osr = pdm_get_ors(dclk_idx, runtime->rate);
                if (!osr)
                        return -EINVAL;
 
                pr_info("%s, pdm_dclk:%d, osr:%d, rate:%d filter mode:%d\n",
                        __func__,
-                       pdm_dclkidx2rate(p_pdm->dclk_idx),
+                       pdm_dclkidx2rate(dclk_idx),
                        osr,
                        runtime->rate,
                        p_pdm->filter_mode);
 
+               info.bitdepth   = bitwidth;
+               info.channels   = runtime->channels;
+               info.lane_masks = p_pdm->lane_mask_in;
+               info.dclk_idx   = dclk_idx;
+               info.bypass     = p_pdm->bypass;
+               info.sample_count = pdm_get_sample_count(p_pdm->isLowPower,
+                                                               dclk_idx);
+
+               aml_pdm_ctrl(&info);
                aml_pdm_filter_ctrl(osr, filter_mode);
 
                if (p_pdm->chipinfo && p_pdm->chipinfo->truncate_data)
@@ -871,6 +984,11 @@ static int aml_pdm_dai_set_sysclk(struct snd_soc_dai *cpu_dai,
 {
        struct aml_pdm *p_pdm = snd_soc_dai_get_drvdata(cpu_dai);
        unsigned int sysclk_srcpll_freq, dclk_srcpll_freq;
+       unsigned int dclk_idx = p_pdm->dclk_idx;
+
+       /* lowpower, force dclk to 768k */
+       if (p_pdm->isLowPower)
+               dclk_idx = 2;
 
        sysclk_srcpll_freq = clk_get_rate(p_pdm->sysclk_srcpll);
        dclk_srcpll_freq = clk_get_rate(p_pdm->dclk_srcpll);
@@ -886,7 +1004,7 @@ static int aml_pdm_dai_set_sysclk(struct snd_soc_dai *cpu_dai,
                clk_set_rate(p_pdm->dclk_srcpll, 24576000);
 #endif
        clk_set_rate(p_pdm->clk_pdm_dclk,
-               pdm_dclkidx2rate(p_pdm->dclk_idx));
+               pdm_dclkidx2rate(dclk_idx));
 
        pr_info("\n%s, pdm_sysclk:%lu pdm_dclk:%lu, dclk_srcpll:%lu\n",
                __func__,
@@ -969,6 +1087,11 @@ void aml_pdm_dai_shutdown(struct snd_pcm_substream *substream,
        p_pdm->clk_on = false;
        p_pdm->rate = 0;
 
+       if (p_pdm->isLowPower) {
+               pdm_force_sysclk_to_oscin(false);
+               vad_set_lowerpower_mode(false);
+       }
+
        /* disable clock and gate */
        clk_disable_unprepare(p_pdm->clk_pdm_dclk);
        clk_disable_unprepare(p_pdm->clk_pdm_sysclk);
@@ -1145,6 +1268,8 @@ static int aml_pdm_platform_probe(struct platform_device *pdev)
                /* defulat set 1 */
                p_pdm->filter_mode = 1;
        }
+       pr_info("%s pdm filter mode from dts:%d\n",
+               __func__, p_pdm->filter_mode);
 
        p_pdm->dev = dev;
        dev_set_drvdata(&pdev->dev, p_pdm);
@@ -1181,23 +1306,55 @@ static int aml_pdm_platform_remove(struct platform_device *pdev)
 
        snd_soc_unregister_component(&pdev->dev);
 
-       snd_soc_unregister_codec(&pdev->dev);
+       snd_soc_unregister_platform(&pdev->dev);
+
+       return 0;
+}
+
+static int pdm_platform_suspend(
+       struct platform_device *pdev, pm_message_t state)
+{
+       struct aml_pdm *p_pdm = dev_get_drvdata(&pdev->dev);
+
+       /* whether in freeze */
+       if (is_pm_freeze_mode()
+               && vad_pdm_is_running()) {
+               pr_info("%s, Entry in freeze\n", __func__);
+               pdm_set_lowpower_mode(p_pdm, true);
+       }
 
        return 0;
 }
 
+static int pdm_platform_resume(
+       struct platform_device *pdev)
+{
+       struct aml_pdm *p_pdm = dev_get_drvdata(&pdev->dev);
+
+       /* whether in freeze mode */
+       if (is_pm_freeze_mode()
+               && vad_pdm_is_running()) {
+               pr_info("%s, Exist from freeze\n", __func__);
+               pdm_set_lowpower_mode(p_pdm, false);
+       }
+
+       return 0;
+}
+
+
 struct platform_driver aml_pdm_driver = {
-       .driver = {
-               .name = DRV_NAME,
-               .owner = THIS_MODULE,
+       .driver  = {
+               .name           = DRV_NAME,
+               .owner          = THIS_MODULE,
                .of_match_table = of_match_ptr(aml_pdm_device_id),
        },
-       .probe = aml_pdm_platform_probe,
-       .remove = aml_pdm_platform_remove,
+       .probe   = aml_pdm_platform_probe,
+       .remove  = aml_pdm_platform_remove,
+       .suspend = pdm_platform_suspend,
+       .resume  = pdm_platform_resume,
 };
 module_platform_driver(aml_pdm_driver);
 
-
 MODULE_AUTHOR("AMLogic, Inc.");
 MODULE_DESCRIPTION("Amlogic PDM ASoc driver");
 MODULE_LICENSE("GPL");
index 877a2fb..e39153a 100644 (file)
@@ -69,6 +69,10 @@ struct aml_pdm {
        struct clk *clk_pdm_sysclk;
        struct clk *clk_pdm_dclk;
        struct toddr *tddr;
+
+       struct pdm_chipinfo *chipinfo;
+       struct snd_kcontrol *controls[PDM_RUN_MAX];
+
        /* sample rate */
        int rate;
        /*
@@ -93,9 +97,6 @@ struct aml_pdm {
 
        /* low power mode, for dclk_sycpll to 24m */
        bool isLowPower;
-
-       struct pdm_chipinfo *chipinfo;
-       struct snd_kcontrol *controls[PDM_RUN_MAX];
 };
 
 #endif /*__AML_PDM_H__*/
index 5b0f06b..4a861ac 100644 (file)
@@ -59,6 +59,11 @@ void pdm_fifo_reset(void)
                0x1 << 16);
 }
 
+void pdm_force_sysclk_to_oscin(bool force)
+{
+       audiobus_update_bits(EE_AUDIO_CLK_PDMIN_CTRL1, 0x1 << 30, force << 30);
+}
+
 void pdm_set_channel_ctrl(int sample_count)
 {
        aml_pdm_write(PDM_CHAN_CTRL, ((sample_count << 24) |
@@ -547,14 +552,16 @@ int pdm_get_ors(int dclk_idx, int sample_rate)
                else if (sample_rate == 8000)
                        osr = 128;
                else
-                       pr_err("Not support rate:%d\n", sample_rate);
+                       pr_err("%s, Not support rate:%d\n",
+                               __func__, sample_rate);
        } else if (dclk_idx == 2) {
                if (sample_rate == 16000)
                        osr = 48;
                else if (sample_rate == 8000)
                        osr = 96;
                else
-                       pr_err("Not support rate:%d\n", sample_rate);
+                       pr_err("%s, Not support rate:%d\n",
+                               __func__, sample_rate);
        } else {
                if (sample_rate == 96000)
                        osr = 32;
@@ -569,7 +576,8 @@ int pdm_get_ors(int dclk_idx, int sample_rate)
                else if (sample_rate == 8000)
                        osr = 384;
                else
-                       pr_err("Not support rate:%d\n", sample_rate);
+                       pr_err("%s, Not support rate:%d\n",
+                               __func__, sample_rate);
        }
 
        return osr;
index b3da8a7..2f0c897 100644 (file)
@@ -34,6 +34,9 @@ struct pdm_info {
 
 extern void aml_pdm_ctrl(struct pdm_info *info);
 
+extern void pdm_force_sysclk_to_oscin(bool force);
+extern void pdm_set_channel_ctrl(int sample_count);
+
 extern void aml_pdm_arb_config(struct aml_audio_controller *actrl);
 
 extern int aml_pmd_set_HPF_filter_parameters(void *array);
index c6ae28f..70705ec 100644 (file)
@@ -107,7 +107,7 @@ enum clk_sel {
 #define EE_AUDIO_CLK_RESAMPLEB_CTRL        0x02e
 #define EE_AUDIO_CLK_SPDIFIN_LB_CTRL       0x02f
 #define EE_AUDIO_CLK_EQDRC_CTRL0           0x030
-#define EE_AUDIO_VAD_CLK_CTRL              0x031
+#define EE_AUDIO_CLK_VAD_CTRL              0x031
 #define EE_AUDIO_EARCTX_CMDC_CLK_CTRL      0x032
 #define EE_AUDIO_EARCTX_DMAC_CLK_CTRL      0x033
 #define EE_AUDIO_EARCRX_CMDC_CLK_CTRL      0x034
index 6a234b2..0d40d68 100644 (file)
@@ -244,9 +244,9 @@ CLOCK_COM_MUX(eqdrc, AUD_ADDR_OFFSET(EE_AUDIO_CLK_EQDRC_CTRL0), 0x7, 24);
 CLOCK_COM_DIV(eqdrc, AUD_ADDR_OFFSET(EE_AUDIO_CLK_EQDRC_CTRL0), 0, 16);
 CLOCK_COM_GATE(eqdrc, AUD_ADDR_OFFSET(EE_AUDIO_CLK_EQDRC_CTRL0), 31);
 /* audio vad  */
-CLOCK_COM_MUX(vad, AUD_ADDR_OFFSET(EE_AUDIO_VAD_CLK_CTRL), 0x7, 24);
-CLOCK_COM_DIV(vad, AUD_ADDR_OFFSET(EE_AUDIO_VAD_CLK_CTRL), 0, 16);
-CLOCK_COM_GATE(vad, AUD_ADDR_OFFSET(EE_AUDIO_VAD_CLK_CTRL), 31);
+CLOCK_COM_MUX(vad, AUD_ADDR_OFFSET(EE_AUDIO_CLK_VAD_CTRL), 0x7, 24);
+CLOCK_COM_DIV(vad, AUD_ADDR_OFFSET(EE_AUDIO_CLK_VAD_CTRL), 0, 16);
+CLOCK_COM_GATE(vad, AUD_ADDR_OFFSET(EE_AUDIO_CLK_VAD_CTRL), 31);
 /* EARC TX CMDC */
 CLOCK_COM_MUX(earctx_cmdc,
        AUD_ADDR_OFFSET(EE_AUDIO_EARCTX_CMDC_CLK_CTRL), 0x7, 24);
index f8d4c7d..7f18e89 100644 (file)
@@ -231,9 +231,9 @@ CLOCK_COM_MUX(eqdrc, AUD_ADDR_OFFSET(EE_AUDIO_CLK_EQDRC_CTRL0), 0x7, 24);
 CLOCK_COM_DIV(eqdrc, AUD_ADDR_OFFSET(EE_AUDIO_CLK_EQDRC_CTRL0), 0, 16);
 CLOCK_COM_GATE(eqdrc, AUD_ADDR_OFFSET(EE_AUDIO_CLK_EQDRC_CTRL0), 31);
 /* audio vad  */
-CLOCK_COM_MUX(vad, AUD_ADDR_OFFSET(EE_AUDIO_VAD_CLK_CTRL), 0x7, 24);
-CLOCK_COM_DIV(vad, AUD_ADDR_OFFSET(EE_AUDIO_VAD_CLK_CTRL), 0, 16);
-CLOCK_COM_GATE(vad, AUD_ADDR_OFFSET(EE_AUDIO_VAD_CLK_CTRL), 31);
+CLOCK_COM_MUX(vad, AUD_ADDR_OFFSET(EE_AUDIO_CLK_VAD_CTRL), 0x7, 24);
+CLOCK_COM_DIV(vad, AUD_ADDR_OFFSET(EE_AUDIO_CLK_VAD_CTRL), 0, 16);
+CLOCK_COM_GATE(vad, AUD_ADDR_OFFSET(EE_AUDIO_CLK_VAD_CTRL), 31);
 
 static int tl1_clks_init(struct clk **clks, void __iomem *iobase)
 {
index aed576e..5dce5ba 100644 (file)
@@ -260,9 +260,9 @@ CLOCK_COM_MUX(eqdrc, AUD_ADDR_OFFSET(EE_AUDIO_CLK_EQDRC_CTRL0), 0x7, 24);
 CLOCK_COM_DIV(eqdrc, AUD_ADDR_OFFSET(EE_AUDIO_CLK_EQDRC_CTRL0), 0, 16);
 CLOCK_COM_GATE(eqdrc, AUD_ADDR_OFFSET(EE_AUDIO_CLK_EQDRC_CTRL0), 31);
 /* audio vad  */
-CLOCK_COM_MUX(vad, AUD_ADDR_OFFSET(EE_AUDIO_VAD_CLK_CTRL), 0x7, 24);
-CLOCK_COM_DIV(vad, AUD_ADDR_OFFSET(EE_AUDIO_VAD_CLK_CTRL), 0, 16);
-CLOCK_COM_GATE(vad, AUD_ADDR_OFFSET(EE_AUDIO_VAD_CLK_CTRL), 31);
+CLOCK_COM_MUX(vad, AUD_ADDR_OFFSET(EE_AUDIO_CLK_VAD_CTRL), 0x7, 24);
+CLOCK_COM_DIV(vad, AUD_ADDR_OFFSET(EE_AUDIO_CLK_VAD_CTRL), 0, 16);
+CLOCK_COM_GATE(vad, AUD_ADDR_OFFSET(EE_AUDIO_CLK_VAD_CTRL), 31);
 /* EARC TX CMDC */
 CLOCK_COM_MUX(earctx_cmdc,
        AUD_ADDR_OFFSET(EE_AUDIO_EARCTX_CMDC_CLK_CTRL), 0x7, 24);
index 8a260bb..5f09029 100644 (file)
@@ -541,6 +541,11 @@ static void vad_deinit(struct vad *p_vad)
        vad_set_clks(p_vad, false);
 }
 
+void vad_set_lowerpower_mode(bool isLowPower)
+{
+       vad_force_clk_to_oscin(isLowPower);
+}
+
 void vad_update_buffer(int isvad)
 {
        struct vad *p_vad = get_vad();
@@ -561,7 +566,7 @@ void vad_update_buffer(int isvad)
                p_vad->start_last = tddr->start_addr;
                p_vad->end_last   = tddr->end_addr;
 
-               rd_th = 0x100;
+               rd_th = 0x800;
 
                pr_debug("Switch to VAD buffer\n");
                pr_debug("\t ASAL start:%x, end:%x, bytes:%d\n",
@@ -1003,7 +1008,8 @@ static int vad_platform_probe(struct platform_device *pdev)
        return 0;
 }
 
-int vad_platform_suspend(struct platform_device *pdev, pm_message_t state)
+static int vad_platform_suspend(
+       struct platform_device *pdev, pm_message_t state)
 {
        struct device *dev = &pdev->dev;
        struct vad *p_vad = dev_get_drvdata(dev);
@@ -1022,7 +1028,8 @@ int vad_platform_suspend(struct platform_device *pdev, pm_message_t state)
        return 0;
 }
 
-int vad_platform_resume(struct platform_device *pdev)
+static int vad_platform_resume(
+       struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        struct vad *p_vad = dev_get_drvdata(dev);
index cd09468..f3964a3 100644 (file)
@@ -44,4 +44,5 @@ extern void vad_set_trunk_data_readable(bool en);
 
 extern int card_add_vad_kcontrols(struct snd_soc_card *card);
 
+extern void vad_set_lowerpower_mode(bool isLowPower);
 #endif
index c122dd0..ba9b2d5 100644 (file)
@@ -107,3 +107,8 @@ void vad_set_enable(bool enable)
                vad_write(VAD_TOP_CTRL1, 0x0);
        }
 }
+
+void vad_force_clk_to_oscin(bool force)
+{
+       audiobus_update_bits(EE_AUDIO_CLK_VAD_CTRL, 0x1 << 30, force << 30);
+}
index 44a1224..af0659c 100644 (file)
@@ -35,4 +35,6 @@ extern void vad_set_src(int src);
 extern void vad_set_in(void);
 
 extern void vad_set_enable(bool enable);
+
+extern void vad_force_clk_to_oscin(bool force);
 #endif