audio: clock only enable in runtime for power consumption
authorXing Wang <xing.wang@amlogic.com>
Tue, 27 Jun 2017 15:22:01 +0000 (23:22 +0800)
committerXing Wang <xing.wang@amlogic.com>
Wed, 28 Jun 2017 08:39:09 +0000 (16:39 +0800)
PD#146592: audio: clock only enable in runtime for power consumption

1. clocks for tdm in & out/spdif in & out/pdm in, only enable when runtime
2. remove unused codes

Change-Id: Ic75ab4557b9e1c26fa032a5b14a7a39ae53f6a06
Signed-off-by: Xing Wang <xing.wang@amlogic.com>
arch/arm64/boot/dts/amlogic/axg_s400.dts
arch/arm64/boot/dts/amlogic/axg_s420.dts
sound/soc/amlogic/auge/card.c
sound/soc/amlogic/auge/iomap.c
sound/soc/amlogic/auge/iomap.h
sound/soc/amlogic/auge/pdm.c
sound/soc/amlogic/auge/pdm_hw.c
sound/soc/amlogic/auge/pdm_hw.h
sound/soc/amlogic/auge/spdif.c
sound/soc/amlogic/auge/tdm.c

index 298bbc4..4da3073 100644 (file)
                                                        <1 1 1 1 1 1 1 1>;
                                dai-tdm-slot-num = <8>;
                                dai-tdm-slot-width = <32>;
-                               system-clock-frequency = <24576000>;
                        };
                        tdmacodec: codec {
                                sound-dai = <&dummy_codec &dummy_codec>;
                                dai-tdm-slot-rx-mask = <1 1>;
                                dai-tdm-slot-num = <2>;
                                dai-tdm-slot-width = <32>;
-                               system-clock-frequency = <12288000>;
                        };
                        codec {
                                prefix-names = "3101_A", "3101_B",
                                dai-tdm-slot-rx-mask = <1 1>;
                                dai-tdm-slot-num = <2>;
                                dai-tdm-slot-width = <32>;
-                               system-clock-frequency = <12288000>;
                        };
                        codec {
                                prefix-names = "5707_A", "5707_B";
                };
 
                aml-audio-card,dai-link@3 {
-                       format = "i2s";
                        mclk-fs = <256>;
-                       continuous-clock;
-                       //bitclock-inversion;
-                       //frame-inversion;
-                       bitclock-master = <&aml_pdm>;
-                       frame-master = <&aml_pdm>;
                        cpu {
                                sound-dai = <&aml_pdm>;
                        };
                };
 
                aml-audio-card,dai-link@4 {
-                       //format = "i2s";
                        mclk-fs = <128>;
-                       continuous-clock;
                        cpu {
                                sound-dai = <&aml_spdif>;
-                               system-clock-frequency = <12288000>;
                        };
                        codec {
                                sound-dai = <&dummy_codec>;
index 710c2c4..1202dd2 100644 (file)
                                dai-tdm-slot-rx-mask = <1 1>;
                                dai-tdm-slot-num = <2>;
                                dai-tdm-slot-width = <32>;
-                               system-clock-frequency = <12288000>;
                        };
                        codec {
                                sound-dai = <&dummy_codec &dummy_codec>;
                                dai-tdm-slot-rx-mask = <1 1>;
                                dai-tdm-slot-num = <2>;
                                dai-tdm-slot-width = <32>;
-                               system-clock-frequency = <12288000>;
                        };
                        codec {
                                sound-dai = <&tas5707_36 &tlv320adc3101_32>;
                                dai-tdm-slot-rx-mask = <1 1>;
                                dai-tdm-slot-num = <2>;
                                dai-tdm-slot-width = <32>;
-                               system-clock-frequency = <12288000>;
                        };
                        codec {
                                sound-dai = <&dummy_codec>;
                };
 
                aml-audio-card,dai-link@3 {
-                       format = "i2s";
                        mclk-fs = <256>;
-                       continuous-clock;
-                       //bitclock-inversion;
-                       //frame-inversion;
-                       bitclock-master = <&aml_pdm>;
-                       frame-master = <&aml_pdm>;
                        cpu {
                                sound-dai = <&aml_pdm>;
                        };
                };
 
                /*aml-audio-card,dai-link@4 {
-                *      //format = "i2s";
                 *      mclk-fs = <128>;
-                *      continuous-clock;
                 *      cpu {
                 *              sound-dai = <&aml_spdif>;
-                *              system-clock-frequency = <12288000>;
                 *      };
                 *      codec {
                 *              sound-dai = <&dummy_codec>;
index 5ec2464..8165574 100644 (file)
@@ -169,6 +169,8 @@ static int aml_card_hw_params(struct snd_pcm_substream *substream,
                mclk_fs = dai_props->mclk_fs;
 
        if (mclk_fs) {
+               struct aml_dai *aml_codec_dai = &dai_props->codec_dai;
+               struct aml_dai *aml_cpu_dai = &dai_props->cpu_dai;
                mclk = params_rate(params) * mclk_fs;
 
                for (i = 0; i < rtd->num_codecs; i++) {
@@ -179,12 +181,31 @@ static int aml_card_hw_params(struct snd_pcm_substream *substream,
 
                        if (ret && ret != -ENOTSUPP)
                                goto err;
+                       ret = snd_soc_dai_set_tdm_slot(codec_dai,
+                                       aml_codec_dai->tx_slot_mask,
+                                       aml_codec_dai->rx_slot_mask,
+                                       aml_codec_dai->slots,
+                                       aml_codec_dai->slot_width);
+                       if (ret && ret != -ENOTSUPP) {
+                               pr_err("aml-card: set_tdm_slot error\n");
+                               goto err;
+                       }
                }
 
                ret = snd_soc_dai_set_sysclk(cpu_dai, 0, mclk,
                                             SND_SOC_CLOCK_OUT);
                if (ret && ret != -ENOTSUPP)
                        goto err;
+
+               ret = snd_soc_dai_set_tdm_slot(cpu_dai,
+                                              aml_cpu_dai->tx_slot_mask,
+                                              aml_cpu_dai->rx_slot_mask,
+                                              aml_cpu_dai->slots,
+                                              aml_cpu_dai->slot_width);
+               if (ret && ret != -ENOTSUPP) {
+                       pr_err("aml-card: set_tdm_slot error\n");
+                       goto err;
+               }
        }
        return 0;
 err:
@@ -200,23 +221,7 @@ static struct snd_soc_ops aml_card_ops = {
 static int aml_card_dai_init(struct snd_soc_pcm_runtime *rtd)
 {
        struct aml_card_data *priv =    snd_soc_card_get_drvdata(rtd->card);
-       struct snd_soc_dai *codec = rtd->codec_dai;
-       struct snd_soc_dai *cpu = rtd->cpu_dai;
-       struct aml_dai_props *dai_props =
-               aml_priv_to_props(priv, rtd->num);
-       int ret, i;
-
-       for (i = 0; i < rtd->num_codecs; i++) {
-               codec = rtd->codec_dais[i];
-
-               ret = aml_card_init_dai(codec, &dai_props->codec_dai);
-               if (ret < 0)
-                       return ret;
-       }
-
-       ret = aml_card_init_dai(cpu, &dai_props->cpu_dai);
-       if (ret < 0)
-               return ret;
+       int ret;
 
        ret = aml_card_init_hp(rtd->card, &priv->hp_jack, PREFIX);
        if (ret < 0)
index a457ba4..2876200 100644 (file)
@@ -93,6 +93,33 @@ void aml_pdm_update_bits(unsigned int reg,
 }
 EXPORT_SYMBOL(aml_pdm_update_bits);
 
+int audiobus_read(unsigned int reg)
+{
+       int ret, val = 0;
+
+       ret = aml_snd_read(IO_AUDIO_BUS, reg, &val);
+
+       if (ret) {
+               pr_err("read audio reg %x error %d\n", reg, ret);
+               return -1;
+       }
+       return val;
+}
+EXPORT_SYMBOL(audiobus_read);
+
+void audiobus_write(unsigned int reg, unsigned int val)
+{
+       aml_snd_write(IO_AUDIO_BUS, reg, val);
+}
+EXPORT_SYMBOL(audiobus_write);
+
+void audiobus_update_bits(unsigned int reg,
+               unsigned int mask, unsigned int val)
+{
+       aml_snd_update_bits(IO_AUDIO_BUS, reg, mask, val);
+}
+EXPORT_SYMBOL(audiobus_update_bits);
+
 static int snd_iomap_probe(struct platform_device *pdev)
 {
        struct resource res;
index 4d5bdd7..4137a47 100644 (file)
@@ -32,4 +32,11 @@ extern void aml_pdm_write(unsigned int reg, unsigned int val);
 extern void aml_pdm_update_bits(unsigned int reg,
        unsigned int mask, unsigned int val);
 
+extern int audiobus_read(unsigned int reg);
+
+extern void audiobus_write(unsigned int reg, unsigned int val);
+
+extern void audiobus_update_bits(unsigned int reg,
+       unsigned int mask, unsigned int val);
+
 #endif
index 5ecbcc1..20b244e 100644 (file)
@@ -133,47 +133,6 @@ static int pdm_hcic_shift_gain_set_enum(
        return 0;
 }
 
-static int aml_pdm_cntrl_get_reg(struct snd_kcontrol *kcontrol,
-               struct snd_ctl_elem_value *ucontrol) {
-       struct soc_mixer_control *mixcntrl =
-               (struct soc_mixer_control *)kcontrol->private_value;
-       unsigned int reg = mixcntrl->reg;
-       unsigned int shift = mixcntrl->shift;
-       unsigned int max = mixcntrl->max;
-       unsigned int invert = mixcntrl->invert;
-       unsigned int value = (((unsigned int)
-               aml_pdm_read(reg))
-               >> shift) & max;
-
-       if (invert)
-               value = (~value) & max;
-       ucontrol->value.integer.value[0] = value;
-
-       return 0;
-}
-
-static int aml_pdm_cntrl_set_reg(struct snd_kcontrol *kcontrol,
-               struct snd_ctl_elem_value *ucontrol) {
-       struct soc_mixer_control *mixcntrl =
-               (struct soc_mixer_control *)kcontrol->private_value;
-       unsigned int reg = mixcntrl->reg;
-       unsigned int shift = mixcntrl->shift;
-       unsigned int max = mixcntrl->max;
-       unsigned int invert = mixcntrl->invert;
-       unsigned int value = ucontrol->value.integer.value[0];
-       unsigned int reg_value = (unsigned int)
-               aml_pdm_read(reg);
-
-       if (invert)
-               value = (~value) & mixcntrl->max;
-       max = ~(max << shift);
-       reg_value &= max;
-       reg_value |= (value << shift);
-       aml_pdm_write(reg, reg_value);
-
-       return 0;
-}
-
 static const struct snd_kcontrol_new snd_pdm_controls[] = {
        /* which set */
        SOC_ENUM_EXT("PDM Filter Mode",
@@ -181,13 +140,7 @@ static const struct snd_kcontrol_new snd_pdm_controls[] = {
                     aml_pdm_filter_mode_get_enum,
                     aml_pdm_filter_mode_set_enum),
 
-       /* hcis gain controls */
-       SOC_SINGLE_EXT("HCIC shift gain",
-                        PDM_HCIC_CTRL1, 24, 0x3F, 0,
-                        aml_pdm_cntrl_get_reg,
-                        aml_pdm_cntrl_set_reg
-                        ),
-
+       /* fix HCIC shift gain according current dmic */
        SOC_ENUM_EXT("HCIC shift gain from coeff",
                     pdm_hcic_shift_gain_enum,
                     pdm_hcic_shift_gain_get_enum,
@@ -455,13 +408,13 @@ EXPORT_SYMBOL_GPL(aml_soc_platform_pdm);
 static int aml_pdm_dai_hw_params(
        struct snd_pcm_substream *substream,
        struct snd_pcm_hw_params *params,
-       struct snd_soc_dai *dai)
+       struct snd_soc_dai *cpu_dai)
 {
        return 0;
 }
 
 static int aml_pdm_dai_set_fmt(
-       struct snd_soc_dai *dai, unsigned int fmt)
+       struct snd_soc_dai *cpu_dai, unsigned int fmt)
 {
        return 0;
 }
@@ -469,9 +422,9 @@ static int aml_pdm_dai_set_fmt(
 
 static int aml_pdm_dai_prepare(
        struct snd_pcm_substream *substream,
-       struct snd_soc_dai *dai)
+       struct snd_soc_dai *cpu_dai)
 {
-       struct aml_pdm *p_pdm = snd_soc_dai_get_drvdata(dai);
+       struct aml_pdm *p_pdm = snd_soc_dai_get_drvdata(cpu_dai);
        struct snd_pcm_runtime *runtime = substream->runtime;
        unsigned int bitwidth;
        unsigned int toddr_type, lsb;
@@ -536,9 +489,9 @@ static int aml_pdm_dai_prepare(
 
 static int aml_pdm_dai_trigger(
        struct snd_pcm_substream *substream, int cmd,
-               struct snd_soc_dai *dai)
+               struct snd_soc_dai *cpu_dai)
 {
-       struct aml_pdm *p_pdm = snd_soc_dai_get_drvdata(dai);
+       struct aml_pdm *p_pdm = snd_soc_dai_get_drvdata(cpu_dai);
 
        pr_info("%s\n", __func__);
 
@@ -589,23 +542,11 @@ static int aml_pdm_dai_set_sysclk(struct snd_soc_dai *cpu_dai,
        return 0;
 }
 
-static int aml_pdm_dai_set_bclk_ratio(struct snd_soc_dai *cpu_dai,
-                                               unsigned int ratio)
-{
-       /* struct aml_pdm *p_pdm = snd_soc_dai_get_drvdata(cpu_dai);
-        *
-        * pr_info("%s ratio:%d\n", __func__, ratio);
-        * aml_pdm_set_bclk_ratio(p_pdm->actrl, ratio);
-        */
-
-       return 0;
-}
-
-static int aml_pdm_dai_probe(struct snd_soc_dai *dai)
+static int aml_pdm_dai_probe(struct snd_soc_dai *cpu_dai)
 {
        int ret = 0;
 
-       ret = snd_soc_add_dai_controls(dai, snd_pdm_controls,
+       ret = snd_soc_add_dai_controls(cpu_dai, snd_pdm_controls,
                                ARRAY_SIZE(snd_pdm_controls));
        if (ret < 0) {
                pr_err("%s, failed add snd pdm controls\n", __func__);
@@ -617,13 +558,63 @@ static int aml_pdm_dai_probe(struct snd_soc_dai *dai)
        return 0;
 }
 
+int aml_pdm_dai_startup(struct snd_pcm_substream *substream,
+       struct snd_soc_dai *cpu_dai)
+{
+       struct aml_pdm *p_pdm = snd_soc_dai_get_drvdata(cpu_dai);
+       int ret;
+
+       if (substream->stream != SNDRV_PCM_STREAM_CAPTURE)
+               return -EINVAL;
+
+       /* enable clock gate */
+       ret = clk_prepare_enable(p_pdm->clk_gate);
+
+       /* enable clock */
+       ret = clk_prepare_enable(p_pdm->clk_pll);
+       if (ret) {
+               pr_err("Can't enable pcm clk_pll clock: %d\n", ret);
+               goto err;
+       }
+
+       ret = clk_prepare_enable(p_pdm->clk_pdm_sysclk);
+       if (ret) {
+               pr_err("Can't enable pcm clk_pdm_sysclk clock: %d\n", ret);
+               goto err;
+       }
+
+       ret = clk_prepare_enable(p_pdm->clk_pdm_dclk);
+       if (ret) {
+               pr_err("Can't enable pcm clk_pdm_dclk clock: %d\n", ret);
+               goto err;
+       }
+
+       return 0;
+err:
+       pr_err("failed enable clock\n");
+       return -EINVAL;
+}
+
+void aml_pdm_dai_shutdown(struct snd_pcm_substream *substream,
+       struct snd_soc_dai *cpu_dai)
+{
+       struct aml_pdm *p_pdm = snd_soc_dai_get_drvdata(cpu_dai);
+
+       /* disable clock and gate */
+       clk_disable_unprepare(p_pdm->clk_pdm_dclk);
+       clk_disable_unprepare(p_pdm->clk_pdm_sysclk);
+       clk_disable_unprepare(p_pdm->clk_pll);
+       clk_disable_unprepare(p_pdm->clk_gate);
+}
+
 static struct snd_soc_dai_ops aml_pdm_dai_ops = {
        .set_fmt        = aml_pdm_dai_set_fmt,
        .hw_params      = aml_pdm_dai_hw_params,
        .prepare        = aml_pdm_dai_prepare,
        .trigger        = aml_pdm_dai_trigger,
        .set_sysclk     = aml_pdm_dai_set_sysclk,
-       .set_bclk_ratio = aml_pdm_dai_set_bclk_ratio,
+       .startup = aml_pdm_dai_startup,
+       .shutdown = aml_pdm_dai_shutdown,
 };
 
 struct snd_soc_dai_driver aml_pdm_dai[] = {
@@ -691,7 +682,6 @@ static int aml_pdm_platform_probe(struct platform_device *pdev)
                        "Can't get pdm gate\n");
                return PTR_ERR(p_pdm->clk_gate);
        }
-       clk_prepare_enable(p_pdm->clk_gate);
 
        /* pinmux */
        p_pdm->pdm_pins = devm_pinctrl_get_select(&pdev->dev, "pdm_pins");
@@ -750,27 +740,6 @@ static int aml_pdm_platform_probe(struct platform_device *pdev)
                goto err;
        }
 
-       /* enable clock */
-       ret = clk_prepare_enable(p_pdm->clk_pll);
-       if (ret) {
-               dev_err(&pdev->dev,
-                       "Can't enable pcm clk_pll clock: %d\n", ret);
-               goto err;
-       }
-
-       ret = clk_prepare_enable(p_pdm->clk_pdm_sysclk);
-       if (ret) {
-               dev_err(&pdev->dev,
-                       "Can't enable pcm clk_pdm_sysclk clock: %d\n", ret);
-               goto err;
-       }
-
-       ret = clk_prepare_enable(p_pdm->clk_pdm_dclk);
-       if (ret) {
-               dev_err(&pdev->dev,
-                       "Can't enable pcm clk_pdm_dclk clock: %d\n", ret);
-               goto err;
-       }
 
        ret = of_property_read_u32(node, "filter_mode",
                        &p_pdm->filter_mode);
index 9c903c5..52463ef 100644 (file)
@@ -84,36 +84,6 @@ void aml_pdm_arb_config(struct aml_audio_controller *actrl)
        aml_audiobus_write(actrl, EE_AUDIO_ARB_CTRL, 1<<31|0xff<<0);
 }
 
-void aml_pdm_set_bclk_ratio(
-       struct aml_audio_controller *actrl,
-       int ratio)
-{
-       unsigned int clk_id;
-       unsigned int mul;
-       unsigned int sample_count = ratio / 2;
-
-       pr_info("%s, ratio:%d, count:%d\n", __func__, ratio, sample_count);
-
-       clk_id = 2; /* according to dts, mpll2 */
-
-       /* sysclk */
-       mul = 1;
-       aml_audiobus_write(actrl, EE_AUDIO_CLK_PDMIN_CTRL1,
-                                       1 << 31 | /* clk enable */
-                                       clk_id << 24 | /* clk src */
-                                       (mul - 1)/* clk_div */
-                                       );
-       /* dclk */
-       mul = ratio;
-       aml_audiobus_write(actrl, EE_AUDIO_CLK_PDMIN_CTRL0,
-                                       1 << 31 | /* clk enable */
-                                       clk_id << 24 | /* clk src */
-                                       (mul - 1)); /* clk_div */
-
-
-}
-
-
 /* config for hcic, lpf1,2,3, hpf */
 static void aml_pdm_filters_config(int osr,
        int lpf1_len, int lpf2_len, int lpf3_len)
index 5f4a9d6..7fc7333 100644 (file)
@@ -25,10 +25,6 @@ extern void aml_pdm_ctrl(
 
 extern void aml_pdm_arb_config(struct aml_audio_controller *actrl);
 
-extern void aml_pdm_set_bclk_ratio(
-       struct aml_audio_controller *actrl,
-       int ratio);
-
 extern int aml_pmd_set_HPF_filter_parameters(void *array);
 
 extern void aml_pdm_filter_ctrl(int osr, int set);
index 4d6f4b3..ad6d68c 100644 (file)
@@ -161,6 +161,16 @@ static int aml_spdif_open(struct snd_pcm_substream *substream)
                                                p_spdif->irq_toddr);
                        return ret;
                }
+
+               ret = request_irq(p_spdif->irq_spdifin,
+                               aml_spdifin_status_isr, 0, "irq_spdifin",
+                               p_spdif);
+               if (ret) {
+                       dev_err(p_spdif->dev, "failed to claim irq_spdifin %u\n",
+                                               p_spdif->irq_spdifin);
+                       //return ret;
+               }
+
        }
 
        runtime->private_data = p_spdif;
@@ -182,6 +192,7 @@ static int aml_spdif_close(struct snd_pcm_substream *substream)
        } else {
                aml_audio_unregister_toddr(p_spdif->dev, p_spdif->to_ddr_num);
                free_irq(p_spdif->irq_toddr, substream);
+               free_irq(p_spdif->irq_spdifin, p_spdif);
        }
 
        runtime->private_data = NULL;
@@ -301,74 +312,15 @@ struct snd_soc_platform_driver aml_spdif_platform = {
 
 static int aml_dai_spdif_probe(struct snd_soc_dai *cpu_dai)
 {
-       struct aml_spdif *p_spdif = snd_soc_dai_get_drvdata(cpu_dai);
-       struct device *dev = p_spdif->dev;
-       int ret;
-
-       /* gate on */
-       clk_prepare_enable(p_spdif->gate_spdifin);
-       clk_prepare_enable(p_spdif->gate_spdifout);
-
-       ret = clk_set_parent(p_spdif->clk_spdifin, p_spdif->fixed_clk);
-       if (ret) {
-               dev_err(dev,
-                       "Can't set clk_spdifin parent clock\n");
-               ret = PTR_ERR(p_spdif->clk_spdifin);
-               return ret;
-       }
-
-       clk_set_rate(p_spdif->clk_spdifin, 250000000);
-       ret = clk_prepare_enable(p_spdif->clk_spdifin);
-       if (ret) {
-               dev_err(dev,
-                       "Can't enable pcm clk_spdifin clock: %d\n", ret);
-               return ret;
-       }
-
-       ret = clk_set_parent(p_spdif->clk_spdifout, p_spdif->sysclk);
-       if (ret) {
-               dev_err(dev,
-                       "Can't set clk_spdifout parent clock\n");
-               ret = PTR_ERR(p_spdif->clk_spdifout);
-               return ret;
-       }
-
-       /* enable clock */
-       ret = clk_prepare_enable(p_spdif->clk_spdifout);
-       if (ret) {
-               dev_err(dev,
-                       "Can't enable pcm clk_spdifout clock: %d\n", ret);
-               return ret;
-       }
-
-       ret = request_irq(p_spdif->irq_spdifin,
-                       aml_spdifin_status_isr, 0, "irq_spdifin", p_spdif);
-       if (ret) {
-               dev_err(p_spdif->dev, "failed to claim irq_spdifin %u\n",
-                                       p_spdif->irq_spdifin);
-               return ret;
-       }
+       pr_info("asoc debug: %s-%d\n", __func__, __LINE__);
 
        return 0;
 }
 
 static int aml_dai_spdif_remove(struct snd_soc_dai *cpu_dai)
 {
-       struct aml_spdif *p_spdif = snd_soc_dai_get_drvdata(cpu_dai);
-
        pr_info("asoc debug: %s-%d\n", __func__, __LINE__);
 
-       free_irq(p_spdif->irq_spdifin, p_spdif);
-       free_irq(p_spdif->irq_frddr, p_spdif);
-       free_irq(p_spdif->irq_toddr, p_spdif);
-
-       clk_disable_unprepare(p_spdif->clk_spdifin);
-       clk_disable_unprepare(p_spdif->clk_spdifout);
-       clk_disable_unprepare(p_spdif->sysclk);
-       clk_disable_unprepare(p_spdif->fixed_clk);
-       clk_disable_unprepare(p_spdif->gate_spdifin);
-       clk_disable_unprepare(p_spdif->gate_spdifout);
-
        return 0;
 }
 
@@ -377,20 +329,70 @@ static int aml_dai_spdif_startup(
        struct snd_soc_dai *cpu_dai)
 {
        struct aml_spdif *p_spdif = snd_soc_dai_get_drvdata(cpu_dai);
+       int ret;
 
        pr_info("asoc debug: %s-%d\n", __func__, __LINE__);
 
        aml_spdif_fifo_reset(p_spdif->actrl, substream->stream);
 
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+               /* enable clock gate */
+
+               ret = clk_prepare_enable(p_spdif->gate_spdifout);
+               /* enable clock */
+               ret = clk_prepare_enable(p_spdif->sysclk);
+               if (ret) {
+                       pr_err("Can't enable pcm sysclk clock: %d\n", ret);
+                       goto err;
+               }
+               ret = clk_prepare_enable(p_spdif->clk_spdifout);
+               if (ret) {
+                       pr_err("Can't enable pcm clk_spdifout clock: %d\n",
+                               ret);
+                       goto err;
+               }
+
+       } else {
+               /* enable clock gate */
+               ret = clk_prepare_enable(p_spdif->gate_spdifin);
+               /* enable clock */
+               ret = clk_prepare_enable(p_spdif->fixed_clk);
+               if (ret) {
+                       pr_err("Can't enable pcm fixed_clk clock: %d\n", ret);
+                       goto err;
+               }
+               ret = clk_prepare_enable(p_spdif->clk_spdifin);
+               if (ret) {
+                       pr_err("Can't enable pcm clk_spdifin clock: %d\n", ret);
+                       goto err;
+               }
+       }
+
        return 0;
+err:
+       pr_err("failed enable clock\n");
+       return -EINVAL;
 }
 
 static void aml_dai_spdif_shutdown(
        struct snd_pcm_substream *substream,
-       struct snd_soc_dai *dai)
+       struct snd_soc_dai *cpu_dai)
 {
+       struct aml_spdif *p_spdif = snd_soc_dai_get_drvdata(cpu_dai);
+
+       /* disable clock and gate */
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+               clk_disable_unprepare(p_spdif->clk_spdifout);
+               clk_disable_unprepare(p_spdif->sysclk);
+               clk_disable_unprepare(p_spdif->gate_spdifout);
+       } else {
+               clk_disable_unprepare(p_spdif->clk_spdifin);
+               clk_disable_unprepare(p_spdif->fixed_clk);
+               clk_disable_unprepare(p_spdif->gate_spdifin);
+       }
 }
 
+
 static int aml_dai_spdif_prepare(
        struct snd_pcm_substream *substream,
        struct snd_soc_dai *cpu_dai)
@@ -491,13 +493,19 @@ static int aml_dai_spdif_hw_params(struct snd_pcm_substream *substream,
                                struct snd_pcm_hw_params *params,
                                struct snd_soc_dai *cpu_dai)
 {
+       struct aml_spdif *p_spdif = snd_soc_dai_get_drvdata(cpu_dai);
        unsigned int rate = params_rate(params);
        int ret = 0;
 
        pr_info("%s\n", __func__);
-       rate *= 128;
-       snd_soc_dai_set_sysclk(cpu_dai,
-                       0, rate, SND_SOC_CLOCK_OUT);
+       if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+               rate *= 128;
+
+               snd_soc_dai_set_sysclk(cpu_dai,
+                               0, rate, SND_SOC_CLOCK_OUT);
+       } else {
+               clk_set_rate(p_spdif->clk_spdifin, 250000000);
+       }
 
        return ret;
 }
@@ -515,7 +523,8 @@ static void aml_set_spdifclk(struct aml_spdif *p_spdif)
 {
        unsigned int mpll_freq = 0;
 
-       pr_info("asoc debug: %s-%d\n", __func__, __LINE__);
+       pr_info("asoc debug: %s-%d, sys freq:%d\n", __func__, __LINE__,
+               p_spdif->sysclk_freq);
        if (p_spdif->sysclk_freq) {
                unsigned int mul = 4;
 
@@ -534,6 +543,7 @@ static int aml_dai_set_spdif_sysclk(struct snd_soc_dai *cpu_dai,
        p_spdif->sysclk_freq = freq;
        pr_info("aml_dai_set_spdif_sysclk, %d, %d, %d\n",
                        clk_id, freq, dir);
+
        aml_set_spdifclk(p_spdif);
 
        return 0;
@@ -580,6 +590,7 @@ static const struct snd_soc_component_driver aml_spdif_component = {
 static int aml_spdif_clks_parse_of(struct aml_spdif *p_spdif)
 {
        struct device *dev = p_spdif->dev;
+       int ret = 0;
 
        /* clock gate */
        p_spdif->gate_spdifin = devm_clk_get(dev, "gate_spdifin");
@@ -618,6 +629,22 @@ static int aml_spdif_clks_parse_of(struct aml_spdif *p_spdif)
                return PTR_ERR(p_spdif->clk_spdifout);
        }
 
+       ret = clk_set_parent(p_spdif->clk_spdifin, p_spdif->fixed_clk);
+       if (ret) {
+               dev_err(dev,
+                       "Can't set clk_spdifin parent clock\n");
+               ret = PTR_ERR(p_spdif->clk_spdifin);
+               return ret;
+       }
+
+       ret = clk_set_parent(p_spdif->clk_spdifout, p_spdif->sysclk);
+       if (ret) {
+               dev_err(dev,
+                       "Can't set clk_spdifout parent clock\n");
+               ret = PTR_ERR(p_spdif->clk_spdifout);
+               return ret;
+       }
+
        return 0;
 }
 
index 6ba4b42..0e0886d 100644 (file)
@@ -332,12 +332,31 @@ struct snd_soc_platform_driver aml_tdm_platform = {
 static int aml_dai_tdm_startup(struct snd_pcm_substream *substream,
                               struct snd_soc_dai *cpu_dai)
 {
-       return 0;
+       struct aml_tdm *p_tdm = snd_soc_dai_get_drvdata(cpu_dai);
+       int ret;
+
+       aml_tdm_fifo_reset(p_tdm->actrl, substream->stream, p_tdm->id);
+
+       ret = clk_prepare_enable(p_tdm->clk);
+       if (ret) {
+               pr_err("Can't enable mpll clock: %d\n", ret);
+               goto err;
+       }
+
+       return ret;
+err:
+       pr_err("failed enable clock\n");
+       return ret;
 }
 
 static void aml_dai_tdm_shutdown(struct snd_pcm_substream *substream,
-                                struct snd_soc_dai *dai)
+                                struct snd_soc_dai *cpu_dai)
 {
+       struct aml_tdm *p_tdm = snd_soc_dai_get_drvdata(cpu_dai);
+
+       /* disable clock and gate */
+       clk_disable_unprepare(p_tdm->clk);
+
 }
 
 static int aml_dai_tdm_prepare(struct snd_pcm_substream *substream,
@@ -731,26 +750,16 @@ static int aml_dai_set_tdm_slot(struct snd_soc_dai *cpu_dai,
 static int aml_dai_tdm_probe(struct snd_soc_dai *cpu_dai)
 {
        struct aml_tdm *p_tdm = snd_soc_dai_get_drvdata(cpu_dai);
-       struct device *dev = p_tdm->dev;
-       int ret;
 
        /* config ddr arb */
        aml_tdm_arb_config(p_tdm->actrl);
 
-       ret = clk_prepare_enable(p_tdm->clk);
-       if (ret) {
-               dev_err(dev, "Can't enable mpll clock: %d\n", ret);
-               return ret;
-       }
-
        return 0;
 }
 
 static int aml_dai_tdm_remove(struct snd_soc_dai *cpu_dai)
 {
-       struct aml_tdm *p_tdm = snd_soc_dai_get_drvdata(cpu_dai);
 
-       clk_disable_unprepare(p_tdm->clk);
        return 0;
 }